1 /*
2 
3                           Firewall Builder
4 
5                  Copyright (C) 2002 NetCitadel, LLC
6 
7   Author:  Vadim Kurland     vadim@vk.crocodile.org
8 
9   $Id$
10 
11   This program is free software which we release under the GNU General Public
12   License. You may redistribute and/or modify this program under the terms
13   of that license as published by the Free Software Foundation; either
14   version 2 of the License, or (at your option) any later version.
15 
16   This program is distributed in the hope that it will be useful,
17   but WITHOUT ANY WARRANTY; without even the implied warranty of
18   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19   GNU General Public License for more details.
20 
21   To get a copy of the GNU General Public License, write to the Free Software
22   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23 
24 */
25 
26 #include "config.h"
27 
28 #include "NATCompiler_pf.h"
29 
30 #include "fwcompiler/OSConfigurator.h"
31 
32 #include "fwbuilder/AddressRange.h"
33 #include "fwbuilder/AddressTable.h"
34 #include "fwbuilder/Cluster.h"
35 #include "fwbuilder/FailoverClusterGroup.h"
36 #include "fwbuilder/Firewall.h"
37 #include "fwbuilder/Host.h"
38 #include "fwbuilder/ICMPService.h"
39 #include "fwbuilder/IPService.h"
40 #include "fwbuilder/IPv4.h"
41 #include "fwbuilder/Interface.h"
42 #include "fwbuilder/Library.h"
43 #include "fwbuilder/NAT.h"
44 #include "fwbuilder/Network.h"
45 #include "fwbuilder/RuleElement.h"
46 #include "fwbuilder/TCPService.h"
47 #include "fwbuilder/UDPService.h"
48 
49 #include <iostream>
50 #include <iomanip>
51 
52 #include <assert.h>
53 
54 using namespace libfwbuilder;
55 using namespace fwcompiler;
56 using namespace std;
57 
myPlatformName()58 string NATCompiler_pf::myPlatformName() { return "pf"; }
59 
60 
prolog()61 int NATCompiler_pf::prolog()
62 {
63     int n=NATCompiler::prolog();
64 
65     if ( n>0 )
66     {
67 	list<FWObject*> l2=fw->getByType(Interface::TYPENAME);
68 	for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
69         {
70 	    Interface *iface=dynamic_cast<Interface*>(*i);
71 	    assert(iface);
72 
73             if ( iface->isDyn())
74             {
75                 iface->setBool("use_var_address",true);
76 
77 /* dynamic interface should not have IPv4 child object(s). We issue a
78  * warning if it does in a policy compiler, there is no need to repeat
79  * it here
80  */
81                 list<FWObject*> l3=iface->getByType(IPv4::TYPENAME);
82                 for (list<FWObject*>::iterator j=l3.begin(); j!=l3.end(); ++j)
83                     iface->remove(*j);
84             }
85 	}
86     }
87 
88 /* pseudo-host with ip address 127.0.0.1  We'll use it for redirection
89  * NAT rules
90  */
91     //FWObject    *grp;
92     loopback_address = dbcopy->createIPv4();
93     loopback_address->setName("__loopback_address__");
94     loopback_address->setId(FWObjectDatabase::generateUniqueId()); // "__loopback_address_id__");
95 
96     IPv4::cast(loopback_address)->setAddress(InetAddr::getLoopbackAddr());
97 
98     persistent_objects->add(loopback_address,false);
99 
100     if (tables)
101     {
102         tables->init(dbcopy);
103         if (!getSourceRuleSet()->isTop())
104             tables->setRuleSetName(getRuleSetName());
105     }
106 
107     return n;
108 }
109 
debugPrintRule(libfwbuilder::Rule * r)110 string NATCompiler_pf::debugPrintRule(libfwbuilder::Rule *r)
111 {
112     NATRule *rule = NATRule::cast(r);
113     RuleElementItfOutb *itf_re = rule->getItfOutb();
114     FWObject *rule_iface = FWObjectReference::getObject(itf_re->front());
115     // FWObject *rule_iface = dbcopy->findInIndex(rule->getInterfaceId());
116 
117     return NATCompiler::debugPrintRule(rule) +
118         " " + string( (rule_iface!=NULL)?rule_iface->getName():"") +
119         " (type=" + rule->getRuleTypeAsString() + ")";
120 }
121 
_expand_addr(Rule * rule,FWObject * s,bool expand_cluster_interfaces_fully)122 void NATCompiler_pf::_expand_addr(Rule *rule,
123                                   FWObject *s,
124                                   bool expand_cluster_interfaces_fully)
125 {
126     if (RuleElementTSrc::isA(s))
127     {
128         // do not replace interfaces with their ip addresses in TSrc
129         // to be able to generate "nat ... -> (em0)" command later
130         list<FWObject*> interfaces_in_re;
131         for (FWObject::iterator i1=s->begin(); i1!=s->end(); ++i1)
132         {
133             FWObject *o = FWReference::getObject(*i1);
134             assert(o);
135             if (Interface::isA(o))
136                 interfaces_in_re.push_back(o);
137         }
138         if (interfaces_in_re.size() > 1)
139         {
140             for (list<FWObject*>::iterator i=interfaces_in_re.begin();
141                  i!=interfaces_in_re.end(); ++i) s->removeRef(*i);
142 
143             NATCompiler::_expand_addr(
144                 rule, s, expand_cluster_interfaces_fully);
145 
146             for (list<FWObject*>::iterator i=interfaces_in_re.begin();
147                  i!=interfaces_in_re.end(); ++i) s->addRef(*i);
148 
149         }
150     } else
151         NATCompiler::_expand_addr(
152             rule, s, expand_cluster_interfaces_fully);
153 }
154 
processNext()155 bool NATCompiler_pf::NATRuleType::processNext()
156 {
157     NATRule *rule=getNext(); if (rule==NULL) return false;
158     tmp_queue.push_back(rule);
159 
160     if (rule->getRuleType()!=NATRule::Unknown) return true;
161 
162     RuleElementTSrc *tsrcre = rule->getTSrc();
163     RuleElementTDst *tdstre = rule->getTDst();
164     RuleElementTSrv *tsrvre = rule->getTSrv();
165 
166     Service  *osrv=compiler->getFirstOSrv(rule);
167 
168     Address *tsrc = compiler->getFirstTSrc(rule);
169     Address *tdst = compiler->getFirstTDst(rule);
170     Service *tsrv=compiler->getFirstTSrv(rule);
171 
172     if (rule->getAction() == NATRule::Branch)
173     {
174 	rule->setRuleType(NATRule::NATBranch);
175         if (!tsrcre->isAny() || !tdstre->isAny() || !tsrvre->isAny())
176         {
177             tsrcre->clearChildren();
178             tsrcre->setAnyElement();
179 
180             tdstre->clearChildren();
181             tdstre->setAnyElement();
182 
183             tsrvre->clearChildren();
184             tsrvre->setAnyElement();
185 
186             compiler->warning(
187                     rule,
188                     "Translated Src, Dst and Srv are ignored in the NAT "
189                     "rule with action 'Branch'");
190         }
191         return true;
192     }
193 
194     if (tsrc->isAny() && tdst->isAny() &&
195         (tsrv->isAny() || (tsrv->getId() == osrv->getId()))
196     )
197     {
198 	rule->setRuleType(NATRule::NONAT);
199 	return true;
200     }
201 
202     bool osrv_defines_src_port = false;
203     Q_UNUSED(osrv_defines_src_port);
204     bool osrv_defines_dst_port = false;
205     Q_UNUSED(osrv_defines_dst_port);
206     bool tsrv_translates_src_port = false;
207     bool tsrv_translates_dst_port = false;
208 
209     if (TCPUDPService::cast(osrv))
210     {
211         TCPUDPService *tu_osrv = TCPUDPService::cast(osrv);
212 
213         osrv_defines_src_port =                                         \
214             (tu_osrv->getSrcRangeStart() != 0 && tu_osrv->getDstRangeStart() == 0);
215         osrv_defines_dst_port =                                         \
216             (tu_osrv->getSrcRangeStart() == 0 && tu_osrv->getDstRangeStart() != 0);
217     }
218 
219     if (TCPUDPService::cast(tsrv))
220     {
221         TCPUDPService *tu_tsrv = TCPUDPService::cast(tsrv);
222 
223         tsrv_translates_src_port =                                      \
224             (tu_tsrv->getSrcRangeStart() != 0 && tu_tsrv->getDstRangeStart() == 0);
225         tsrv_translates_dst_port =                                      \
226             (tu_tsrv->getSrcRangeStart() == 0 && tu_tsrv->getDstRangeStart() != 0);
227     }
228 
229 
230     if (
231         (! tsrc->isAny() && tdst->isAny()) ||
232         (tsrc->isAny() && tdst->isAny() && tsrv_translates_src_port)
233     )
234     {
235         rule->setRuleType(NATRule::SNAT);
236 	return true;
237     }
238 
239     if (
240         (tsrc->isAny() && ! tdst->isAny()) ||
241         (tsrc->isAny() && tdst->isAny() && tsrv_translates_dst_port)
242     )
243     {
244 /* this is load balancing rule if there are multiple objects in TDst */
245         if ( tdstre->size()>1 ) rule->setRuleType(NATRule::LB);
246         else
247         {
248 
249             if ( compiler->complexMatch(tdst,compiler->fw) ) rule->setRuleType(NATRule::Redirect);
250             else                                             rule->setRuleType(NATRule::DNAT);
251 
252 //            if ( tdst->getId()==compiler->fw->getId() ) rule->setRuleType(NATRule::Redirect);
253 //            else                                        rule->setRuleType(NATRule::DNAT);
254         }
255         return true;
256     }
257 
258     if (
259         ( ! tsrc->isAny() && ! tdst->isAny() ) ||
260         ( ! tsrc->isAny() && tsrv_translates_dst_port) ||
261         ( ! tdst->isAny() && tsrv_translates_src_port)
262     )
263     {
264         rule->setRuleType(NATRule::SDNAT);
265 	return true;
266     }
267 
268     compiler->abort(rule, "Unsupported translation.");
269 
270     return false;
271 }
272 
273 /*
274  * This processor should be called after classifyNATRule. Should call
275  * classifyNATRule after this processor again.
276  *
277  * This algorithm is very much specific to iptables. Platforms where
278  * this simple algorithm for SDNAT rules is not appropriate, should
279  * either implement equivalent of this processor using different
280  * algorithm, or should catch SDNAT rules and abort in their own
281  * verifyNATRule processor.
282  */
processNext()283 bool NATCompiler_pf::splitSDNATRule::processNext()
284 {
285     NATRule *rule=getNext(); if (rule==NULL) return false;
286 
287     if ( rule->getRuleType()==NATRule::SDNAT)
288     {
289         RuleElementODst *odst;
290         RuleElementOSrv *osrv;
291         RuleElementTSrc *tsrc;
292         RuleElementTDst *tdst;
293 
294 /* first rule translates destination and may translate service (depends
295  * on the original rule) */
296         NATRule *r =  compiler->dbcopy->createNATRule();
297         r->duplicate(rule);
298         compiler->temp_ruleset->add(r);
299         r->setRuleType(NATRule::Unknown);
300 
301         tsrc=r->getTSrc();
302         tsrc->clearChildren();
303         tsrc->setAnyElement();
304 
305         tmp_queue.push_back(r);
306 
307 /* the second rule translates source and uses translated object in
308  * ODst. Since the service could have been translated by the first
309  * rule, we use TSrv in OSrv */
310         r = compiler->dbcopy->createNATRule();
311         r->duplicate(rule);
312         compiler->temp_ruleset->add(r);
313         r->setRuleType(NATRule::Unknown);
314 
315         odst=r->getODst();
316         odst->clearChildren();
317         for (FWObject::iterator i=rule->getTDst()->begin(); i!=rule->getTDst()->end(); i++)
318         {
319             FWObject *o = FWReference::getObject(*i);
320             odst->addRef(o);
321         }
322 
323         if ( ! rule->getTSrv()->isAny())
324         {
325             /*
326              * See "pf flow diagram" at  http://homepage.mac.com/quension/pf/flow.png
327              * rdr happens first, then nat. This means nat sees packet with
328              * translated destination address and port.
329              *
330              * If the first rule in the pair translated service and
331              * changed destination port, we need to match it in the
332              * second rule to only trsnslate source in the packets
333              * that have been processed by the first rule. However
334              * this only applies to the case when destination port has
335              * been translated because the first rule uses DNAT which
336              * can only translate dest. port. So, if TSrv has zero
337              * dest.  port range but non-zero source port range, we
338              * should not match it here because in this case no
339              * dest. port translation occurs.  If TSrv translates both
340              * source and destination ports, we create new TCP(UDP)
341              * service object with only dest. port part and use it to
342              * match.
343              */
344             Service *tsrv = compiler->getFirstTSrv(rule);
345             TCPUDPService *tu_tsrv = TCPUDPService::cast(tsrv);
346             if (tu_tsrv && tu_tsrv->getDstRangeStart() != 0)
347             {
348                 TCPUDPService *match_service = NULL;
349                 if (tu_tsrv->getSrcRangeStart() == 0)
350                 {
351                     // no source port tranlsation
352                     match_service = tu_tsrv;
353                 } else
354                 {
355                     // both source and dest port translation occurs
356                     match_service = TCPUDPService::cast(
357                         compiler->dbcopy->create(tsrv->getTypeName()));
358                     match_service->setName(tsrv->getName() + "_dport");
359                     compiler->persistent_objects->add(match_service);
360                     match_service->setDstRangeStart(tu_tsrv->getDstRangeStart());
361                     match_service->setDstRangeEnd(tu_tsrv->getDstRangeEnd());
362                 }
363                 osrv = r->getOSrv();
364                 osrv->clearChildren();
365                 osrv->addRef(match_service);
366             }
367         }
368 
369         tdst=r->getTDst();
370         tdst->clearChildren();
371         tdst->setAnyElement();
372 
373         tmp_queue.push_back(r);
374     }
375     else
376         tmp_queue.push_back(rule);
377 
378     return true;
379 }
380 
381 
processNext()382 bool NATCompiler_pf::VerifyRules::processNext()
383 {
384     NATRule *rule=getNext(); if (rule==NULL) return false;
385 
386     string version = compiler->fw->getStr("version");
387 
388     RuleElementOSrc  *osrc=rule->getOSrc();  assert(osrc);
389     RuleElementODst  *odst=rule->getODst();  assert(odst);
390     RuleElementOSrv  *osrv=rule->getOSrv();  assert(osrv);
391 
392     RuleElementTSrc  *tsrc=rule->getTSrc();  assert(tsrc);
393     RuleElementTDst  *tdst=rule->getTDst();  assert(tdst);
394     RuleElementTSrv  *tsrv=rule->getTSrv();  assert(tsrv);
395 
396     /*
397      * because of the change in the nat and rdr rules syntax in
398      * 4.7, I can no longer implement no-nat rules correctly for
399      * this version. They dropped the "no" keyword and their
400      * examples suggest using "pass" to implement exclusions for
401      * the nat rules. I need no-nat rule to just not translate but
402      * not make a decision whether the packet should be passed or
403      * dropped. In the new PF model, translation rules are just
404      * options on the matching policy rules and they do not offer
405      * any keyword or option to not translate.
406      */
407     if (rule->getRuleType()==NATRule::NONAT &&
408         XMLTools::version_compare(version, "4.7")>=0)
409     {
410         compiler->abort(
411             rule,
412             "No translation rules are not supported for PF 4.7, "
413             "use negation to implement exclusions");
414         return true;
415     }
416 
417     if (osrv->getNeg())
418     {
419         compiler->abort(
420             rule,
421             "Negation in original service is not supported.");
422         return true;
423     }
424 
425     /* bug #1276083: "Destination NAT rules". this restriction is not
426      * true at least as of OpenBSD 3.5
427      *
428     if (rule->getRuleType()==NATRule::DNAT && osrv->isAny())
429 	compiler->abort("Service must be specified for destination translation rule. Rule "+rule->getLabel());
430     */
431 
432     if (rule->getRuleType()==NATRule::DNAT && osrv->isAny() && !tsrv->isAny())
433     {
434 	compiler->abort(
435             rule,
436             "Can not translate 'any' into a specific service.");
437         return true;
438     }
439 
440     if (tsrc->getNeg())
441     {
442         compiler->abort(
443             rule,
444             "Can not use negation in translated source.");
445         return true;
446     }
447 
448     if (tdst->getNeg())
449     {
450         compiler->abort(
451             rule,
452             "Can not use negation in translated destination.");
453         return true;
454     }
455 
456     if (tsrv->getNeg())
457     {
458         compiler->abort(
459             rule,
460             "Can not use negation in translated service.");
461         return true;
462     }
463 
464     if (tsrv->size()!=1)
465     {
466 	compiler->abort(
467             rule,
468             "Translated service should be 'Original' or should contain single object.");
469         return true;
470     }
471 
472     FWObject *o=tsrv->front();
473     if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
474 
475     if ( Group::cast(o)!=NULL)
476     {
477 	compiler->abort(
478             rule,
479             "Can not use group in translated service.");
480         return true;
481     }
482 
483 #if 0
484     if (rule->getRuleType()==NATRule::SNAT )
485     {
486         Address* o1=compiler->getFirstTSrc(rule);
487         if ( Network::cast(o1)!=NULL || AddressRange::cast(o1)!=NULL )
488             compiler->abort("Can not use network or address range object in translated source. Rule "+rule->getLabel());
489     }
490 #endif
491 
492     if (rule->getRuleType()==NATRule::SNAT )
493     {
494         if (tsrc->isAny())
495         {
496             compiler->abort(rule,
497                             "Source translation rule needs an address in "
498                             "Translated Source.");
499             return true;
500         }
501 
502         FWObject *o = FWReference::getObject(tsrc->front());
503         if (Interface::isA(o) && Interface::cast(o)->isUnnumbered())
504         {
505             compiler->abort(rule,
506                             "Can not use unnumbered interface in "
507                             "Translated Source of a Source translation rule.");
508             return true;
509         }
510 
511     }
512 
513     if (rule->getRuleType()==NATRule::DNAT || rule->getRuleType()==NATRule::Redirect )
514     {
515         if (tdst->isAny())
516         {
517             compiler->abort(
518                 rule,
519                 "Destination translation rule needs an address in "
520                 "Translated Destination.");
521             return true;
522         }
523 
524         if ( tdst->size()!=1)
525         {
526             compiler->abort(
527                 rule,
528                 "There should be no more than one object in translated destination");
529             return true;
530         }
531 
532         Address* o1=compiler->getFirstTDst(rule);
533         if ( Network::cast(o1)!=NULL || AddressRange::cast(o1)!=NULL )
534         {
535             compiler->abort(
536                 rule,
537                 "Can not use network or address range object in translated destination.");
538             return true;
539         }
540 
541     }
542 
543 
544     if (rule->getRuleType()==NATRule::SNetnat && !tsrc->isAny() )
545     {
546         Network *a1=Network::cast(compiler->getFirstOSrc(rule));
547         Network *a2=Network::cast(compiler->getFirstTSrc(rule));
548         if ( a1==NULL || a2==NULL ||
549              a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
550         {
551             compiler->abort(
552                 rule,
553                 "Original and translated source should both be networks of the same size.");
554             return true;
555         }
556 
557     }
558 
559     if (rule->getRuleType()==NATRule::DNetnat && !tsrc->isAny() )
560     {
561         Network *a1=Network::cast(compiler->getFirstODst(rule));
562         Network *a2=Network::cast(compiler->getFirstTDst(rule));
563         if ( a1==NULL || a2==NULL ||
564              a1->getNetmaskPtr()->getLength()!=a2->getNetmaskPtr()->getLength() )
565         {
566             compiler->abort(
567                 rule,
568                 "Original and translated destination should both be networks of the same size.");
569             return true;
570         }
571 
572     }
573 
574     if (rule->getRuleType()==NATRule::NATBranch )
575     {
576         RuleSet *branch = rule->getBranch();
577         if (branch == NULL)
578         {
579             compiler->abort(
580                 rule,
581                 "Action 'Branch' needs NAT rule set to point to");
582             return true;
583         } else
584         {
585             if (!NAT::isA(branch))
586             {
587                 compiler->abort(
588                     rule,
589                     "Action 'Branch' must point to a NAT rule set "
590                     "(points to " + branch->getTypeName() + ")");
591                 return true;
592             }
593 
594         }
595     }
596 
597     tmp_queue.push_back(rule);
598     return true;
599 }
600 
processNext()601 bool NATCompiler_pf::splitOnOSrv::processNext()
602 {
603     NATRule *rule=getNext(); if (rule==NULL) return false;
604 
605     RuleElementOSrv  *osrv=rule->getOSrv();  assert(osrv);
606     if (osrv->size()!=1)
607     {
608 	for(list<FWObject*>::iterator i=osrv->begin(); i!=osrv->end(); ++i)
609         {
610 	    FWObject *o= *i;
611 //	    if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
612 	    if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
613 	    Service *s=Service::cast( o );
614 	    assert(s);
615 
616 	    NATRule *r= compiler->dbcopy->createNATRule();
617 	    compiler->temp_ruleset->add(r);
618 	    r->duplicate(rule);
619 	    RuleElementOSrv *nosrv=r->getOSrv();
620 	    nosrv->clearChildren();
621 
622 	    nosrv->addRef( s );
623 
624 	    tmp_queue.push_back( r );
625 	}
626     } else
627 	tmp_queue.push_back(rule);
628 
629     return true;
630 }
631 
processNext()632 bool NATCompiler_pf::fillTranslatedSrv::processNext()
633 {
634     NATRule *rule=getNext(); if (rule==NULL) return false;
635     tmp_queue.push_back(rule);
636 
637     Service  *osrv_o=compiler->getFirstOSrv(rule);
638     Service  *tsrv_o=compiler->getFirstTSrv(rule);
639 
640     if ( ! osrv_o->isAny()  && tsrv_o->isAny() )
641     {
642 	RuleElementTSrv  *tsrv=rule->getTSrv();
643 	tsrv->addRef(osrv_o);
644     }
645     return true;
646 }
647 
processNext()648 bool NATCompiler_pf::addVirtualAddress::processNext()
649 {
650     NATRule *rule=getNext(); if (rule==NULL) return false;
651     tmp_queue.push_back(rule);
652 
653     Address *a=NULL;
654     if (rule->getRuleType()==NATRule::SNAT) a=compiler->getFirstTSrc(rule);
655     else
656 	if (rule->getRuleType()==NATRule::DNAT) a=compiler->getFirstODst(rule);
657 	else  return true;
658     assert(a!=NULL);
659     const InetAddr *a_addr = a->getAddressPtr();
660 
661     if ( ! a->isAny() && a->getId()!=compiler->getFwId() && a_addr)
662     {
663 	list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
664 	for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
665         {
666 	    Interface *iface=dynamic_cast<Interface*>(*i);
667 	    assert(iface);
668             const InetAddr *iface_addr = iface->getAddressPtr();
669 	    if (iface_addr && *a_addr == *iface_addr )
670                 return true;
671 	}
672 	compiler->osconfigurator->addVirtualAddressForNAT( a );
673     }
674 
675     return true;
676 }
677 
678 
processNext()679 bool NATCompiler_pf::splitForTSrc::processNext()
680 {
681     NATRule *rule=getNext(); if (rule==NULL) return false;
682     RuleElementTSrc  *tsrc=rule->getTSrc();  assert(tsrc);
683 
684     map<int,list<FWObject*> > interfaceGroups;
685 
686     for(list<FWObject*>::iterator i=tsrc->begin(); i!=tsrc->end(); ++i)
687     {
688         FWObject *o= *i;
689         if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
690         Interface *iface = compiler->findInterfaceFor(Address::cast(o),
691                                                       compiler->fw);
692         if (iface!=NULL)
693             interfaceGroups[iface->getId()].push_back(o);
694     }
695 
696     if (interfaceGroups.size()<=1) tmp_queue.push_back(rule);
697     else
698     {
699         map<int,list<FWObject*> >::iterator i;
700         for (i=interfaceGroups.begin(); i!=interfaceGroups.end(); i++)
701         {
702             list<FWObject*> &objSubset = (*i).second;
703 
704             RuleElementTSrc  *ntsrc = NULL;
705             NATRule *r = compiler->dbcopy->createNATRule();
706             r->duplicate(rule);
707             compiler->temp_ruleset->add(r);
708 
709             ntsrc=r->getTSrc();
710             ntsrc->clearChildren();
711             ntsrc->setAnyElement();
712             for (FWObject::iterator j=objSubset.begin(); j!=objSubset.end(); j++)
713             {
714                 ntsrc->addRef(*j);
715             }
716             tmp_queue.push_back(r);
717         }
718     }
719     return true;
720 }
721 
722 
assignInterfaceToNATRule(NATRule * rule,Address * addr)723 bool NATCompiler_pf::assignInterfaceToNATRule(NATRule *rule, Address *addr)
724 {
725     RuleElementItfOutb *itf_re = rule->getItfOutb();
726     assert(itf_re!=NULL);
727 
728     if (Interface::isA(addr) || IPv4::isA(addr))
729     {
730         FWObject *p = addr;
731         while ( p && ! Interface::isA(p) ) p = p->getParent();
732         Interface *intf = Interface::cast(p);
733 
734         if (intf && intf->isFailoverInterface())
735         {
736             FailoverClusterGroup *fg = FailoverClusterGroup::cast(
737                 intf->getFirstByType(FailoverClusterGroup::TYPENAME));
738             if (fg)
739                 intf = fg->getInterfaceForMemberFirewall(fw);
740         }
741 
742         if (intf && intf->isChildOf(fw))
743         {
744             if ( ! itf_re->hasRef(intf)) itf_re->addRef(intf);
745             return true;
746         }
747     }
748     return false;
749 }
750 
processNext()751 bool NATCompiler_pf::AssignInterface::processNext()
752 {
753     NATCompiler_pf *pf_comp = dynamic_cast<NATCompiler_pf*>(compiler);
754     NATRule *rule = getNext(); if (rule==NULL) return false;
755 
756     if (rule->getStr(".iface") == "nil")
757     {
758         tmp_queue.push_back(rule);
759         return true;
760     }
761 
762     RuleElementItfOutb *itf_re = rule->getItfOutb();
763     assert(itf_re!=NULL);
764 
765     if ( ! itf_re->isAny())
766     {
767         tmp_queue.push_back(rule);
768         return true;
769     }
770 
771     switch ( rule->getRuleType() )
772     {
773     case NATRule::SNAT:
774     {
775         RuleElementTSrc *tsrc_re = rule->getTSrc();
776         bool have_interface = false;
777         for (FWObject::iterator i1=tsrc_re->begin(); i1!=tsrc_re->end(); ++i1)
778         {
779             Address *addr = Address::cast(FWObjectReference::getObject(*i1));
780             have_interface |= pf_comp->assignInterfaceToNATRule(rule, addr);
781         }
782 
783         if (have_interface)
784         {
785             tmp_queue.push_back(rule);
786             return true;
787         }
788 
789 /* if we appear here, then TSrc is not an interface or address of
790  * an interface. Generate NAT rule without "on iface" clause
791  */
792 //        rule->setInterfaceStr("");
793         itf_re->clearChildren();
794         itf_re->setAnyElement();
795     }
796     break;
797 
798     case NATRule::DNAT:
799     {
800         RuleElementODst *odst_re = rule->getODst();
801         bool have_interface = false;
802         for (FWObject::iterator i1=odst_re->begin(); i1!=odst_re->end(); ++i1)
803         {
804             Address *addr = Address::cast(FWObjectReference::getObject(*i1));
805             have_interface |= pf_comp->assignInterfaceToNATRule(rule, addr);
806         }
807 
808         if (have_interface)
809         {
810             tmp_queue.push_back(rule);
811             return true;
812         }
813 
814 /* if we appear here, then ODst is not an interface or address of an
815  * interface. If this is so, just do not specify interface for rdr
816  * rule.
817  */
818         itf_re->clearChildren();
819         itf_re->setAnyElement();
820     }
821     break;
822 
823     default: break;
824     }
825 
826     tmp_queue.push_back(rule);
827     return true;
828 }
829 
830 
831 /*
832  *  I assume that there is always only one object in ODst, TSrc and TDst
833  *  rule elements. This should have been assured by inspector VerifyRules
834  */
processNext()835 bool NATCompiler_pf::ReplaceFirewallObjectsODst::processNext()
836 {
837     NATRule *rule=getNext(); if (rule==NULL) return false;
838     tmp_queue.push_back(rule);
839 
840     list<FWObject*> cl;
841     RuleElementODst *rel;
842     Address *obj=NULL;
843 
844     rel = rule->getODst();      assert(rel);
845     obj =compiler->getFirstODst(rule);  assert(obj);
846 
847     if (obj->getId()==compiler->getFwId() )
848     {
849 	list<FWObject*> l2 = compiler->fw->getByTypeDeep(Interface::TYPENAME);
850 	for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
851         {
852 	    Interface *interface_ = Interface::cast(*i);
853 /*
854  * update 03/20/03:
855  *
856  * generally we assume that if firewall object is used in the rule,
857  * then any or all its interface will be used. This means that if
858  * firewall is in ODst we should really use all of its interfaces, not
859  * only external ones.
860  */
861             if (! interface_->isLoopback() ) cl.push_back(interface_);
862 
863 	}
864 	if ( ! cl.empty() )
865         {
866 	    rel->clearChildren();
867 	    for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
868 	    {
869 		rel->addRef( *i1 );
870 	    }
871 	}
872 /*
873  * update for ticket 1397 If firewall object is in ODst, do not assign
874  * the rule to any interface.  I use attribute ".iface" to signal
875  * AssignInterface that it should not do anything.
876  */
877         rule->setStr(".iface", "nil");
878     }
879 
880     return true;
881 }
882 
883 /*
884  *  I assume that there is always only one object in ODst, TSrc and TDst
885  *  rule elements. This should have been assured by inspector VerifyRules
886  */
processNext()887 bool NATCompiler_pf::ReplaceFirewallObjectsTSrc::processNext()
888 {
889     NATRule *rule=getNext(); if (rule==NULL) return false;
890     tmp_queue.push_back(rule);
891 
892     list<FWObject*> cl;
893     RuleElementTSrc *rel;
894     Address         *obj=NULL;
895 
896     switch (rule->getRuleType())
897     {
898     case NATRule::Masq:   return true;
899     default:
900 	rel=rule->getTSrc();      assert(rel);
901 	obj=compiler->getFirstTSrc(rule);  assert(obj);
902 
903 	if (obj->getId()==compiler->getFwId() )
904         {
905             Address *odst=compiler->getFirstODst(rule);
906 
907             rel->clearChildren();
908 
909             Interface *iface=compiler->findInterfaceFor(odst,compiler->fw);
910 
911             if (!odst->isAny() && !rule->getODst()->getNeg() && iface!=NULL)
912                 rel->addRef(iface);
913             else  // else use all interfaces except loopback and unnumbered ones
914             {
915                 list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
916                 for (list<FWObject*>::iterator i=l2.begin(); i!=l2.end(); ++i)
917                 {
918                     Interface *iface=Interface::cast(*i);
919                     if (! iface->isLoopback() &&
920                         ! iface->isUnnumbered() &&
921                         ! iface->isBridgePort())
922                         rel->addRef( *i );
923                 }
924                 for (FWObject::iterator i1=cl.begin(); i1!=cl.end(); ++i1)
925                     rel->addRef( *i1 );
926 
927 /* it is an error if rule element is empty at this point. this could have
928  * happened if all external interfaces are unnumbered */
929                 if (rel->size()==0)
930                 {
931                     QString err(
932                         "Could not find suitable interface for the NAT rule %1. "
933                         "Perhaps all interfaces are unnumbered?");
934                     compiler->abort(
935                         rule,
936                         err.arg(rule->getLabel().c_str()).toStdString());
937                 }
938             }
939 	}
940     }
941     return true;
942 }
943 
944 /*
945  *  I assume that there is always only one object in ODst, TSrc and TDst
946  *  rule elements. This should have been assured by inspector VerifyRules
947  */
processNext()948 bool NATCompiler_pf::ReplaceObjectsTDst::processNext()
949 {
950     NATRule *rule=getNext(); if (rule==NULL) return false;
951     NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
952 
953     tmp_queue.push_back(rule);
954 
955     if (rule->getRuleType()==NATRule::Redirect)
956     {
957         Service         *tsrv=compiler->getFirstTSrv(rule);
958         RuleElementTDst *rel=rule->getTDst();          assert(rel);
959         Address         *otdst=compiler->getFirstTDst(rule);
960         Interface       *loopback=NULL;
961         FWObject        *loopback_address=NULL;
962 
963 /* if firewall is used in TDst in redirection rule, replace it with
964  * its loopback interface
965  */
966         if (otdst->getId()==compiler->fw->getId())
967         {
968             std::list<FWObject*> l2=compiler->fw->getByType(Interface::TYPENAME);
969             for (std::list<FWObject*>::iterator i=l2.begin();
970                  i!=l2.end(); ++i)
971             {
972                 Interface *iface = dynamic_cast<Interface*>(*i);
973                 assert(iface);
974                 if (iface->isLoopback())
975                 {
976                     loopback = iface;
977                     loopback_address = loopback->getFirstByType(IPv4::TYPENAME);
978                 }
979             }
980 
981             if (loopback_address==NULL)
982             {
983                 compiler->abort(rule,
984                                 "Can not configure redirection for the NAT rule "
985                                 "because loopback interface is missing.");
986             }
987 
988             rel->clearChildren();
989             rel->addRef( loopback_address );
990 
991             pf_comp->redirect_rules.push_back(
992                 redirectRuleInfo( rule->getLabel(), otdst,
993                                   loopback_address, tsrv ) );
994         }
995     }
996     return true;
997 }
998 
999 
processNext()1000 bool NATCompiler_pf::swapAddressTableObjectsInRE::processNext()
1001 {
1002     NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
1003     Rule *rule=prev_processor->getNextRule(); if (rule==NULL) return false;
1004 
1005     RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
1006 
1007     list<MultiAddress*> cl;
1008     for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
1009     {
1010         FWObject *o= *i;
1011         if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
1012         /*
1013          * All addressTable objects will be run-time here because we
1014          * switch them in preprocessor. The difference is: if address
1015          * table was originally run-time, at this point it will have
1016          * no children, however if it was compile-time originally, it
1017          * will have children objects.  That is how we distinguish
1018          * them in this rule processor. Here we only deal with
1019          * AddressTable objects that originally used to be
1020          * compile-time because we need to create tables for them.
1021          */
1022         if (AddressTable::cast(o)!=NULL &&
1023             AddressTable::cast(o)->isRunTime() &&
1024             o->size() > 0)
1025             cl.push_back(MultiAddress::cast(o));
1026     }
1027 
1028     if (!cl.empty())
1029     {
1030         for (list<MultiAddress*>::iterator i=cl.begin(); i!=cl.end(); i++)
1031         {
1032             MultiAddress *atbl = *i;
1033 
1034             // Need to make sure the ID of the MultiAddressRunTime
1035             // object created here is stable and is always the same
1036             // for the same MultiAddress object. In particular this
1037             // ensures that we reuse tables between policy and NAT rules
1038             string mart_id_str = FWObjectDatabase::getStringId(atbl->getId()) +
1039                 "_runtime";
1040             int mart_id = FWObjectDatabase::registerStringId(mart_id_str);
1041 
1042             MultiAddressRunTime *mart =
1043                 MultiAddressRunTime::cast(compiler->dbcopy->findInIndex(mart_id));
1044             if (mart==NULL)
1045             {
1046                 mart = new MultiAddressRunTime(atbl);
1047 
1048                 // need to ensure stable ID for the runtime object, so
1049                 // that when the same object is replaced in different
1050                 // rulesets by different compiler passes, chosen
1051                 // runtime object has the same ID and is identified as
1052                 // the same by the compiler.
1053 
1054                 mart->setId( mart_id );
1055                 compiler->dbcopy->addToIndex(mart);
1056                 compiler->persistent_objects->add(mart);
1057 
1058 // register this object as a table
1059                 string tblname = atbl->getName();
1060                 string tblID = tblname + "_addressTableObject";
1061                 pf_comp->tables->registerTable(tblname,tblID,atbl);
1062             }
1063 
1064             re->removeRef(atbl);
1065             re->addRef(mart);
1066         }
1067         tmp_queue.push_back(rule);
1068         return true;
1069     }
1070 
1071     tmp_queue.push_back(rule);
1072     return true;
1073 }
1074 
1075 
processNext()1076 bool NATCompiler_pf::processMultiAddressObjectsInRE::processNext()
1077 {
1078     NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
1079     NATRule *rule=getNext(); if (rule==NULL) return false;
1080 
1081     RuleElement *re=RuleElement::cast( rule->getFirstByType(re_type) );
1082     bool neg = re->getNeg();
1083 
1084     list<FWObject*> cl;
1085 
1086     try
1087     {
1088         for (FWObject::iterator i=re->begin(); i!=re->end(); i++)
1089         {
1090             FWObject *o= *i;
1091             if (FWReference::cast(o)!=NULL) o=FWReference::cast(o)->getPointer();
1092 
1093             MultiAddressRunTime *atrt = MultiAddressRunTime::cast(o);
1094             if (atrt!=NULL && atrt->getSubstitutionTypeName()==AddressTable::TYPENAME)
1095             {
1096                 if (re->size()>1 && neg)
1097                 {
1098                     string err = "AddressTable object can not be used with "
1099                         "negation in combination with other objects "
1100                         "in the same rule element.";
1101                     compiler->abort(rule, err);
1102                 }
1103                 o->setBool("pf_table",true);
1104                 string tblname = o->getName();
1105                 string tblID = tblname + "_addressTableObject";
1106                 pf_comp->tables->registerTable(tblname,tblID,o);
1107                 cl.push_back(o);
1108             }
1109         }
1110     } catch(FWException &ex)  // TableFactory::registerTable throws exception
1111     {
1112         string err;
1113         err = "Can not process MultiAddress object in rule " +
1114             rule->getLabel() + ". Error: " + ex.toString();
1115         compiler->abort(rule,  err);
1116     }
1117 
1118     if (!cl.empty())
1119     {
1120         RuleElement *nre;
1121 
1122         for (FWObject::iterator i=cl.begin(); i!=cl.end(); i++)
1123         {
1124             NATRule *r= compiler->dbcopy->createNATRule();
1125             compiler->temp_ruleset->add(r);
1126             r->duplicate(rule);
1127             nre=RuleElement::cast( r->getFirstByType(re_type) );
1128             nre->clearChildren();
1129             nre->addRef( *i );
1130             tmp_queue.push_back(r);
1131         }
1132 
1133         for (FWObject::iterator i=cl.begin(); i!=cl.end(); i++)
1134             re->removeRef( *i );
1135 
1136         if (!re->isAny())
1137             tmp_queue.push_back(rule);
1138 
1139         return true;
1140     }
1141 
1142     tmp_queue.push_back(rule);
1143     return true;
1144 }
1145 
1146 
1147 
findDynamicInterfaces(RuleElement * re,Rule * rule)1148 void NATCompiler_pf::checkForDynamicInterfacesOfOtherObjects::findDynamicInterfaces(RuleElement *re,
1149                                                                                      Rule        *rule)
1150 {
1151     if (re->isAny()) return;
1152     list<FWObject*> cl;
1153     for (list<FWObject*>::iterator i1=re->begin(); i1!=re->end(); ++i1)
1154     {
1155         FWObject *o = *i1;
1156         FWObject *obj = o;
1157         if (FWReference::cast(o)!=NULL) obj=FWReference::cast(o)->getPointer();
1158         Interface  *ifs = Interface::cast(obj);
1159 
1160         if (ifs && Cluster::isA(ifs->getParent()))
1161         {
1162             FailoverClusterGroup *failover_group =
1163                 FailoverClusterGroup::cast(
1164                     ifs->getFirstByType(FailoverClusterGroup::TYPENAME));
1165             if (failover_group)
1166             {
1167                 for (FWObjectTypedChildIterator it =
1168                          failover_group->findByType(FWObjectReference::TYPENAME);
1169                      it != it.end(); ++it)
1170                 {
1171                     Interface *member_iface = Interface::cast(FWObjectReference::getObject(*it));
1172                     assert(member_iface);
1173                     if (member_iface->isChildOf(compiler->fw))
1174                     {
1175                         ifs = member_iface;
1176                         break;
1177                     }
1178                 }
1179             }
1180         }
1181 
1182         if (ifs && ifs->isDyn() && ! ifs->isChildOf(compiler->fw))
1183         {
1184             QString err(
1185                 "Can not build rule using dynamic interface '%1' "
1186                 "of the object '%2' because its address is unknown.");
1187             compiler->abort(
1188                 rule, err
1189                 .arg(ifs->getName().c_str())
1190                 .arg(ifs->getParent()->getName().c_str()).toStdString());
1191         }
1192     }
1193 }
1194 
1195 
processNext()1196 bool NATCompiler_pf::checkForDynamicInterfacesOfOtherObjects::processNext()
1197 {
1198     NATRule *rule=getNext(); if (rule==NULL) return false;
1199 
1200     findDynamicInterfaces( rule->getOSrc() , rule );
1201     findDynamicInterfaces( rule->getODst() , rule );
1202     findDynamicInterfaces( rule->getTSrc() , rule );
1203     findDynamicInterfaces( rule->getTDst() , rule );
1204 
1205     tmp_queue.push_back(rule);
1206     return true;
1207 }
1208 
processNext()1209 bool NATCompiler_pf::createTables::processNext()
1210 {
1211     NATCompiler_pf *pf_comp=dynamic_cast<NATCompiler_pf*>(compiler);
1212     NATRule *rule=getNext(); if (rule==NULL) return false;
1213 
1214     RuleElementOSrc *osrc=rule->getOSrc();
1215     RuleElementODst *odst=rule->getODst();
1216 
1217     if (osrc->size()!=1) pf_comp->tables->createTablesForRE(osrc,rule);
1218     if (odst->size()!=1) pf_comp->tables->createTablesForRE(odst,rule);
1219 
1220 #if 0
1221     RuleElementTSrc *tsrc=rule->getTSrc();
1222     RuleElementTDst *tdst=rule->getTDst();
1223 
1224     if (tsrc->size()!=1) pf_comp->tables->createTablesForRE(tsrc,rule);
1225     if (tdst->size()!=1) pf_comp->tables->createTablesForRE(tdst,rule);
1226 #endif
1227 
1228     tmp_queue.push_back(rule);
1229     return true;
1230 }
1231 
1232 
compile()1233 void NATCompiler_pf::compile()
1234 {
1235     bool manage_virtual_addr=fwopt->getBool("manage_virtual_addr");
1236 
1237     string banner = " Compiling NAT rules for " + fw->getName();
1238     if (!getRuleSetName().empty())  banner += " ruleset " + getRuleSetName();
1239     if (ipv6) banner += ", IPv6";
1240     info(banner);
1241 
1242     Compiler::compile();
1243 
1244     add( new Begin());
1245     add( new printTotalNumberOfRules() );
1246 
1247     add( new singleRuleFilter());
1248 
1249     add(new expandGroupsInItfOutb("expand groups in Interface"));
1250     add(new replaceClusterInterfaceInItfOutb(
1251             "replace cluster interfaces with member interfaces in "
1252             "the Interface rule element"));
1253     add(new singleObjectNegationItfOutb(
1254             "process single object negation in inbound Itf"));
1255     add(new ItfOutbNegation("process negation in Itf"));
1256 
1257     add( new recursiveGroupsInOSrc("check for recursive groups in OSRC") );
1258     add( new recursiveGroupsInODst("check for recursive groups in ODST") );
1259     add( new recursiveGroupsInOSrv("check for recursive groups in OSRV") );
1260 
1261     add( new recursiveGroupsInTSrc("check for recursive groups in TSRC") );
1262     add( new recursiveGroupsInTDst("check for recursive groups in TDST") );
1263     add( new recursiveGroupsInTSrv("check for recursive groups in TSRV") );
1264 
1265     add( new emptyGroupsInOSrc(    "check for empty groups in OSRC"    ) );
1266     add( new emptyGroupsInODst(    "check for empty groups in ODST"    ) );
1267     add( new emptyGroupsInOSrv(    "check for empty groups in OSRV"    ) );
1268 
1269     add( new emptyGroupsInTSrc(    "check for empty groups in TSRC"    ) );
1270     add( new emptyGroupsInTDst(    "check for empty groups in TDST"    ) );
1271     add( new emptyGroupsInTSrv(    "check for empty groups in TSRV"    ) );
1272 
1273     if (fw->getOptionsObject()->getBool("preserve_group_names"))
1274     {
1275         add(new RegisterGroupsAndTablesInOSrc(
1276                 "register object groups and tables in OSrc"));
1277         add(new RegisterGroupsAndTablesInODst(
1278                 "register object groups and tables in ODst"));
1279     }
1280 
1281     add( new ExpandGroups( "expand groups" ) );
1282     add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
1283     add( new eliminateDuplicatesInOSRC(  "eliminate duplicates in OSRC") );
1284     add( new eliminateDuplicatesInODST(  "eliminate duplicates in ODST") );
1285     add( new eliminateDuplicatesInOSRV(  "eliminate duplicates in OSRV") );
1286 
1287     add( new swapMultiAddressObjectsInOSrc(
1288              " swap MultiAddress -> MultiAddressRunTime in OSrc") );
1289     add( new swapMultiAddressObjectsInODst(
1290              " swap MultiAddress -> MultiAddressRunTime in ODst") );
1291     add( new swapMultiAddressObjectsInTSrc(
1292              " swap MultiAddress -> MultiAddressRunTime in TSrc") );
1293     add( new swapMultiAddressObjectsInTDst(
1294              " swap MultiAddress -> MultiAddressRunTime in TDst") );
1295 
1296     add( new swapAddressTableObjectsInOSrc(
1297              "AddressTable -> MultiAddressRunTime in OSrc") );
1298     add( new swapAddressTableObjectsInODst(
1299              "AddressTable -> MultiAddressRunTime in ODst") );
1300     add( new swapAddressTableObjectsInTSrc(
1301              "AddressTable -> MultiAddressRunTime in TSrc") );
1302     add( new swapAddressTableObjectsInTDst(
1303              "AddressTable -> MultiAddressRunTime in TDst") );
1304 
1305     add( new processMultiAddressObjectsInOSrc(
1306              "process MultiAddress objects in OSrc") );
1307     add( new processMultiAddressObjectsInODst(
1308              "process MultiAddress objects in ODst") );
1309     add( new processMultiAddressObjectsInTSrc(
1310              "process MultiAddress objects in TSrc") );
1311     add( new processMultiAddressObjectsInTDst(
1312              "process MultiAddress objects in TDst") );
1313 
1314     add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
1315 
1316     add( new splitOnOSrv( "split rule on original service" ) );
1317     add( new fillTranslatedSrv( "fill translated service" ) );
1318 
1319     //add( new doOSrcNegation( "process negation in OSrc" ) );
1320     //add( new doODstNegation( "process negation in ODst" ) );
1321     //add( new doOSrvNegation( "process negation in OSrv" ) );
1322 
1323     add( new NATRuleType( "determine NAT rule types" ) );
1324     add( new splitSDNATRule("split SDNAT rules"      ) );
1325     add( new NATRuleType( "determine NAT rule types" ) );
1326     add( new VerifyRules( "verify NAT rules" ) );
1327 
1328     add( new ReplaceFirewallObjectsODst(
1329              "replace references to the firewall in ODst" ) );
1330     add( new ReplaceFirewallObjectsTSrc(
1331              "replace references to the firewall in TSrc" ) );
1332 
1333     add( new ReplaceObjectsTDst( "replace objects in TDst" ) );
1334 
1335     add( new ExpandMultipleAddresses( "expand multiple addresses" ) );
1336 
1337     // we might get empty RE after expanding multiple addresses,
1338     // for example when unnumbered interface is used in TSRC. Note
1339     // that VerifyRules should not allow this, but we may still
1340     // get here in the test mode. Calling dropRuleWithEmptyRE works
1341     // as a fail-safe and prevents crash.
1342     add( new dropRuleWithEmptyRE("drop rules with empty rule elements"));
1343 
1344     if ( manage_virtual_addr )
1345         add( new addVirtualAddress("add virtual addresses for NAT rules"));
1346 
1347     add( new checkForUnnumbered("check for unnumbered interfaces" ) );
1348     add( new checkForDynamicInterfacesOfOtherObjects(
1349              "check for dynamic interfaces of other hosts and firewalls"));
1350     add( new ExpandAddressRanges( "expand address range objects" ) );
1351 
1352     add( new splitForTSrc(
1353              "split if addresses in TSrc belong to different networks" ));
1354 
1355     add( new AssignInterface( "assign rules to interfaces" ) );
1356 
1357     add( new checkForObjectsWithErrors(
1358              "check if we have objects with errors in rule elements"));
1359 
1360     add( new createTables("create tables"));
1361 //        add( new PrintTables(       "print tables"     ) );
1362 
1363     add( new PrintRule("generate pf code") );
1364     add( new simplePrintProgress() );
1365 
1366     runRuleProcessors();
1367 
1368 }
1369 
1370 
epilog()1371 void NATCompiler_pf::epilog()
1372 {
1373 }
1374 
~NATCompiler_pf()1375 NATCompiler_pf::~NATCompiler_pf()
1376 {
1377     //if (tables) tables->detach();
1378 }
1379 
1380