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 
27 #include "config.h"
28 
29 #include "OSConfigurator_linux24.h"
30 
31 #include "fwbuilder/InetAddr.h"
32 
33 #include "fwbuilder/Firewall.h"
34 #include "fwbuilder/FWOptions.h"
35 #include "fwbuilder/Interface.h"
36 #include "fwbuilder/IPv4.h"
37 #include "fwbuilder/Network.h"
38 #include "fwbuilder/Address.h"
39 #include "fwbuilder/Resources.h"
40 #include "fwbuilder/MultiAddress.h"
41 #include "fwbuilder/FailoverClusterGroup.h"
42 #include "fwbuilder/XMLTools.h"
43 
44 #include "Configlet.h"
45 
46 #ifndef _WIN32
47 #  include <unistd.h>
48 #endif
49 
50 #include <sys/types.h>
51 #include <sys/stat.h>
52 #include <fcntl.h>
53 #include <ctype.h>
54 
55 #include <algorithm>
56 #include <functional>
57 #include <iostream>
58 
59 #include <assert.h>
60 
61 #include <QString>
62 #include <QtDebug>
63 #include <QRegExp>
64 #include <QStringList>
65 
66 
67 using namespace libfwbuilder;
68 using namespace fwcompiler;
69 using namespace std;
70 
myPlatformName()71 string OSConfigurator_linux24::myPlatformName() { return "Linux24"; }
72 
OSConfigurator_linux24(FWObjectDatabase * _db,Firewall * fw,bool ipv6_policy)73 OSConfigurator_linux24::OSConfigurator_linux24(FWObjectDatabase *_db,
74                                                Firewall *fw,
75                                                bool ipv6_policy) :
76     OSConfigurator(_db, fw, ipv6_policy) , os_data(fw->getStr("host_OS"))
77 {
78     command_wrappers = new Configlet(fw, "linux24", "run_time_wrappers");
79 
80     FWOptions* fwopt = fw->getOptionsObject();
81     string version = fw->getStr("version");
82     using_ipset = (XMLTools::version_compare(version, "1.4.1.1") >= 0 &&
83                           fwopt->getBool("use_m_set"));
84 }
85 
~OSConfigurator_linux24()86 OSConfigurator_linux24::~OSConfigurator_linux24()
87 {
88     delete command_wrappers;
89 }
90 
91 /*
92  * this function generates acceptable shell variable name from
93  * interface name. Note that PolicyCompiler_ipt::getInterfaceVarName()
94  * and NATCompiler_ipt::getInterfaceVarName do the same thing and
95  * these functions should be identical.
96  *
97  * TODO: really need to have one function for this instead of three in
98  * three different classes.
99  */
getInterfaceVarName(FWObject * iface,bool v6)100 string OSConfigurator_linux24::getInterfaceVarName(FWObject *iface, bool v6)
101 {
102     ostringstream  ostr;
103     string iname=iface->getName();
104     string::size_type p1;
105     while ( (p1=iname.find("."))!=string::npos)
106         iname=iname.replace(p1,1,"_");
107     while ( (p1=iname.find("-"))!=string::npos)
108         iname=iname.replace(p1,1,"_");
109     ostr << "i_" << iname;
110     if (v6) ostr << "_v6";
111     return ostr.str();
112 }
113 
setConfigletMacroForOptionStr(const string & s,Configlet * c,const char * option_name)114 void OSConfigurator_linux24::setConfigletMacroForOptionStr(
115     const string &s, Configlet *c, const char *option_name)
116 {
117     // "" means no change, do not include the command in the script
118     if (!s.empty())
119     {
120         c->setVariable(QString("if_") + option_name, 1);
121         c->setVariable(option_name, s.c_str());
122     } else
123     {
124         c->setVariable(QString("if_") + option_name, 0);
125         c->setVariable(option_name, s.c_str());
126     }
127 }
128 
setConfigletMacroForOptionInt(int val,Configlet * c,const char * option_name)129 void OSConfigurator_linux24::setConfigletMacroForOptionInt(
130     int val, Configlet *c, const char *option_name)
131 {
132     // -1 means no change, do not include the command in the script
133     if (val >= 0)
134     {
135         c->setVariable(QString("if_") + option_name, 1);
136         c->setVariable(option_name, val);
137     } else
138     {
139         c->setVariable(QString("if_") + option_name, 0);
140         c->setVariable(option_name, 0);
141     }
142 }
143 
processFirewallOptions()144 void OSConfigurator_linux24::processFirewallOptions()
145 {
146     Configlet kernel_vars(fw, "linux24", "kernel_vars");
147     kernel_vars.removeComments();
148     kernel_vars.collapseEmptyStrings(true);
149 
150     FWOptions* options = fw->getOptionsObject();
151 
152     setConfigletMacroForOptionStr(options->getStr("linux24_ip_dynaddr"), &kernel_vars, "linux24_ip_dynaddr");
153     setConfigletMacroForOptionStr(options->getStr("linux24_rp_filter"), &kernel_vars, "linux24_rp_filter");
154     setConfigletMacroForOptionStr(options->getStr("linux24_accept_source_route"), &kernel_vars, "linux24_accept_source_route");
155     setConfigletMacroForOptionStr(options->getStr("linux24_accept_redirects"), &kernel_vars, "linux24_accept_redirects");
156     setConfigletMacroForOptionStr(options->getStr("linux24_log_martians"), &kernel_vars, "linux24_log_martians");
157     setConfigletMacroForOptionStr(options->getStr("linux24_icmp_echo_ignore_broadcasts"), &kernel_vars, "linux24_icmp_echo_ignore_broadcasts");
158     setConfigletMacroForOptionStr(options->getStr("linux24_icmp_echo_ignore_all"), &kernel_vars, "linux24_icmp_echo_ignore_all");
159     setConfigletMacroForOptionStr(options->getStr("linux24_icmp_ignore_bogus_error_responses"), &kernel_vars, "linux24_icmp_ignore_bogus_error_responses");
160     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_window_scaling"), &kernel_vars, "linux24_tcp_window_scaling");
161     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_sack"), &kernel_vars, "linux24_tcp_sack");
162     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_fack"), &kernel_vars, "linux24_tcp_fack");
163     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_syncookies"), &kernel_vars, "linux24_tcp_syncookies");
164     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_ecn"), &kernel_vars, "linux24_tcp_ecn");
165     setConfigletMacroForOptionStr(options->getStr("linux24_tcp_timestamps"), &kernel_vars, "linux24_tcp_timestamps");
166 
167     int opt = options->getInt("linux24_tcp_fin_timeout");
168     setConfigletMacroForOptionInt((opt==0)?-1:opt, &kernel_vars, "linux24_tcp_fin_timeout");
169     opt = options->getInt("linux24_tcp_keepalive_interval");
170     setConfigletMacroForOptionInt((opt==0)?-1:opt, &kernel_vars, "linux24_tcp_keepalive_interval");
171 
172     Configlet conntrack_vars(fw, "linux24", "conntrack");
173     conntrack_vars.removeComments();
174     conntrack_vars.collapseEmptyStrings(true);
175 
176     string version = fw->getStr("version");
177     bool version_ge_1_4 = XMLTools::version_compare(version, "1.4.0") >= 0;
178     conntrack_vars.setVariable("iptables_version_ge_1_4", version_ge_1_4);
179     conntrack_vars.setVariable("iptables_version_lt_1_4", !version_ge_1_4);
180 
181     // if conntrack_max and conntrack_hashsize are equal to 0, we do
182     // not add commands from the configlet (so the kernel defaults are
183     // used). Options above assume -1 is the default. Need to pass -1
184     // instead of 0 for the conntrack vars
185     opt = options->getInt("linux24_conntrack_max");
186     setConfigletMacroForOptionInt(
187         (opt==0)?-1:opt,
188         &conntrack_vars, "conntrack_max");
189     opt = options->getInt("linux24_conntrack_hashsize");
190     setConfigletMacroForOptionInt(
191         (opt==0)?-1:opt,
192         &conntrack_vars, "conntrack_hashsize");
193 
194     // This option uses three-state control and assumes empty string is the default
195     setConfigletMacroForOptionStr(
196         options->getStr("linux24_conntrack_tcp_be_liberal"),
197         &conntrack_vars, "conntrack_tcp_be_liberal");
198 
199     output << kernel_vars.expand().toStdString();
200     output << endl;
201     output << conntrack_vars.expand().toStdString();
202 }
203 
addVirtualAddressForNAT(const Network * nw)204 void OSConfigurator_linux24::addVirtualAddressForNAT(const Network *nw)
205 {
206     FWOptions* options=fw->getOptionsObject();
207     if (options->getBool("manage_virtual_addr"))
208     {
209         if (virtual_addresses.empty() ||
210             find(virtual_addresses.begin(),virtual_addresses.end(),
211                  *(nw->getAddressPtr())) == virtual_addresses.end())
212         {
213             Interface *iface = findInterfaceFor( nw, fw );
214             if (iface!=NULL)
215             {
216                 const InetAddr *addr = nw->getAddressPtr();
217                 InetAddr first, last;
218                 InetAddr a;
219 
220                 first = *addr;
221                 last = *(nw->getBroadcastAddressPtr());
222 
223                 QStringList addresses;
224                 for (a=first; a<last; a=a+1)
225                 {
226                     addresses.push_back(QString("%1/32").arg(a.toString().c_str()));
227                 }
228 
229                 if (virtual_addresses_for_nat.count(iface->getName()) > 0)
230                     addresses.push_front(virtual_addresses_for_nat[iface->getName()].c_str());
231 
232                 virtual_addresses_for_nat[iface->getName()] =
233                     addresses.join(" ").toStdString();
234 
235                 virtual_addresses.push_back( *(nw->getAddressPtr()) );
236                 registerVirtualAddressForNat();
237             } else
238                 warning("Can not add virtual address " +
239                         nw->getAddressPtr()->toString() +
240                         " (object " + nw->getName() + ")" );
241         }
242     }
243 }
244 
addVirtualAddressForNAT(const Address * addr)245 void OSConfigurator_linux24::addVirtualAddressForNAT(const Address *addr)
246 {
247     FWOptions* options=fw->getOptionsObject();
248     if ( options->getBool("manage_virtual_addr") )
249     {
250         const InetAddr *addr_addr = addr->getAddressPtr();
251 
252         if (virtual_addresses.empty() ||
253             find(virtual_addresses.begin(),
254                  virtual_addresses.end(), *addr_addr) == virtual_addresses.end())
255         {
256             FWObject *vaddr = findAddressFor(addr, fw );
257             if (vaddr!=NULL)
258             {
259                 Interface *iface = Interface::cast(vaddr->getParent());
260                 assert(iface!=NULL);
261 
262                 QStringList addresses;
263                 const InetAddr *vaddr_netm =
264                     Address::cast(vaddr)->getNetmaskPtr();
265 
266                 addresses.push_back(QString("%1/%2").
267                                     arg(addr_addr->toString().c_str()).
268                                     arg(vaddr_netm->getLength()));
269 
270                 if (virtual_addresses_for_nat.count(iface->getName()) > 0)
271                     addresses.push_front(virtual_addresses_for_nat[iface->getName()].c_str());
272 
273                 virtual_addresses_for_nat[iface->getName()] =
274                     addresses.join(" ").toStdString();
275 
276                 virtual_addresses.push_back(*(addr_addr));
277                 registerVirtualAddressForNat();
278             } else
279                 warning("Can not add virtual address for object " + addr->getName());
280         }
281         return;
282     }
283 }
284 
normalizeSetName(const string & txt)285 string OSConfigurator_linux24::normalizeSetName(const string &txt)
286 {
287     QString table_name = txt.c_str();
288     table_name.replace(QRegExp("[ +*!#|]"), "_");
289     return table_name.toStdString();
290 }
291 
registerMultiAddressObject(MultiAddressRunTime * at)292 void OSConfigurator_linux24::registerMultiAddressObject(MultiAddressRunTime *at)
293 {
294     // std::map<std::string,std::string>
295     address_table_objects[normalizeSetName(at->getName())] = at->getSourceName();
296 }
297 
prolog()298 int  OSConfigurator_linux24::prolog()
299 {
300     return 0;
301 }
302 
303 /**
304  * Print shell functions used by the script. If argument (boolean) is true,
305  * do not add comments.
306  */
printShellFunctions(bool have_ipv6)307 string OSConfigurator_linux24::printShellFunctions(bool have_ipv6)
308 {
309     QStringList output;
310     FWOptions* options = fw->getOptionsObject();
311 
312     string version = fw->getStr("version");
313     // string host_os = fw->getStr("host_OS");
314     // string os_family = Resources::os_res[host_os]->
315     //     getResourceStr("/FWBuilderResources/Target/family");
316 
317     Configlet shell_functions(fw, "linux24", "shell_functions");
318     output.push_back(shell_functions.expand());
319 
320 /* check if package iproute2 is installed, but do this only if
321  * we really need /usr/sbin/ip
322  */
323     Configlet configlet(fw, "linux24", "check_utilities");
324     configlet.removeComments();
325     configlet.collapseEmptyStrings(true);
326 
327     configlet.setVariable("load_modules", options->getBool("load_modules"));
328 
329     if (options->getBool("load_modules") ||
330         options->getBool("configure_vlan_interfaces") ||
331         options->getBool("configure_bonding_interfaces"))
332     {
333         configlet.setVariable("need_modprobe", true);
334     }
335 
336     if (options->getBool("verify_interfaces") ||
337         options->getBool("manage_virtual_addr") ||
338         options->getBool("configure_interfaces") )
339     {
340         configlet.setVariable("need_vconfig",
341                               options->getBool("configure_vlan_interfaces"));
342         configlet.setVariable("need_brctl",
343                               options->getBool("configure_bridge_interfaces"));
344         configlet.setVariable("need_ifenslave",
345                               options->getBool("configure_bonding_interfaces"));
346     }
347 
348     configlet.setVariable("need_ipset", using_ipset);
349 
350     configlet.setVariable("need_iptables_restore",
351                           options->getBool("use_iptables_restore"));
352 
353     configlet.setVariable("need_ip6tables_restore",
354                           have_ipv6 && options->getBool("use_iptables_restore"));
355 
356     output.push_back(configlet.expand());
357 
358     /*
359      * Generate commands to reset all tables and chains and set
360      * default policy
361      */
362     Configlet reset_iptables(fw, "linux24", "reset_iptables");
363     if (XMLTools::version_compare(version, "1.4.20") >= 0)
364         reset_iptables.setVariable("opt_wait", "-w");
365     else
366         reset_iptables.setVariable("opt_wait", "");
367 
368     output.push_back(reset_iptables.expand());
369 
370     Configlet addr_conf(fw, "linux24", "update_addresses");
371     output.push_back(addr_conf.expand());
372 
373     if (options->getBool("configure_vlan_interfaces"))
374     {
375         Configlet conf(fw, "linux24", "update_vlans");
376         output.push_back(conf.expand());
377     }
378 
379     if (options->getBool("configure_bridge_interfaces"))
380     {
381         Configlet conf(fw, "linux24", "update_bridge");
382         output.push_back(conf.expand());
383     }
384 
385     if (options->getBool("configure_bonding_interfaces"))
386     {
387         Configlet conf(fw, "linux24", "update_bonding");
388         output.push_back(conf.expand());
389     }
390 
391     return output.join("\n").toStdString();
392 }
393 
printRunTimeAddressTablesCode()394 string OSConfigurator_linux24::printRunTimeAddressTablesCode()
395 {
396     Configlet conf(fw, "linux24", "run_time_address_tables");
397     conf.setVariable("using_ipset", using_ipset);
398 
399     ostringstream check_ostr;
400     ostringstream load_ostr;
401     map<string,string>::iterator i;
402     for (i=address_table_objects.begin(); i!=address_table_objects.end(); ++i)
403     {
404         string at_name = i->first;
405         string at_file = i->second;
406         // If the file name is empty, this run-time table is
407         // completely controlled by the user outside fwbuilder so we
408         // do not need to add commands to check if the file exits and
409         // load it
410         if (!at_file.empty())
411         {
412             check_ostr << "check_file \"" + at_name +
413                 "\" \"" + at_file + "\"" << endl;
414             load_ostr << "reload_address_table \"" + at_name +
415                 "\" \"" + at_file + "\"" << endl;
416         }
417     }
418 
419     conf.setVariable("check_files_commands", check_ostr.str().c_str());
420     conf.setVariable("load_files_commands", load_ostr.str().c_str());
421 
422     return conf.expand().toStdString();
423 }
424 
getPathForATool(const std::string & os_variant,OSData::tools tool_name)425 string OSConfigurator_linux24::getPathForATool(const std::string &os_variant, OSData::tools tool_name)
426 {
427     FWOptions* options = fw->getOptionsObject();
428     string attr = os_data.getAttributeNameForTool(tool_name);
429 
430     string s = options->getStr("linux24_" + attr);
431     if (!s.empty()) return s;
432 
433     string host_os = fw->getStr("host_OS");
434     string r = "/FWBuilderResources/Target/tools/" + os_variant + "/" + attr;
435     if (Resources::os_res[host_os]->getResourceStr(r).empty())
436         r = "/FWBuilderResources/Target/tools/Unknown/" + attr;
437 
438     return Resources::os_res[host_os]->getResourceStr(r);
439 }
440 
printPathForAllTools(const string & os)441 string  OSConfigurator_linux24::printPathForAllTools(const string &os)
442 {
443     ostringstream res;
444 
445     list<int>::const_iterator i;
446     const list<int> &all_tools = os_data.getAllTools();
447     for (i=all_tools.begin(); i!=all_tools.end(); ++i)
448         res << os_data.getVariableName(OSData::tools(*i))
449             << "=\""
450             << getPathForATool(os, OSData::tools(*i))
451             << "\""
452             << endl;
453     return res.str();
454 }
455 
generateCodeForProtocolHandlers()456 string OSConfigurator_linux24::generateCodeForProtocolHandlers()
457 {
458     FWOptions* options = fw->getOptionsObject();
459     bool nomod = Resources::os_res[fw->getStr("host_OS")]->
460         Resources::getResourceBool("/FWBuilderResources/Target/options/suppress_modules");
461 
462     // string host_os = fw->getStr("host_OS");
463     // string os_family = Resources::os_res[host_os]->
464     //     getResourceStr("/FWBuilderResources/Target/family");
465     Configlet load_modules(fw, "linux24", "load_modules");
466     load_modules.removeComments();
467 
468     // See ticket #2
469     string modules_dir = Resources::os_res[fw->getStr("host_OS")]->
470         Resources::getResourceStr("/FWBuilderResources/Target/options/default/modules_dir");
471 
472 /* there is no need to load modules on some platforms */
473     load_modules.setVariable("load_modules", options->getBool("load_modules") && !nomod);
474     load_modules.setVariable("modules_dir", modules_dir.c_str());
475     return load_modules.expand().toStdString();
476 }
477 
addressTableWrapper(FWObject * rule,const QString & command,bool ipv6)478 QString OSConfigurator_linux24::addressTableWrapper(FWObject *rule,
479                                                     const QString &command,
480                                                     bool ipv6)
481 {
482     QString combined_command = command;
483     QRegExp address_table_re("\\$at_(\\S+)");
484     int pos = address_table_re.indexIn(command);
485     if (pos > -1)
486     {
487         QStringList command_lines = QString(command).split("\n", QString::SkipEmptyParts);
488         if (command_lines.size() > 1)
489         {
490             command_lines.push_front("{");
491             command_lines.push_back("}");
492         }
493         combined_command = command_lines.join("\n");
494 
495         command_wrappers->clear();
496         command_wrappers->removeComments();
497         command_wrappers->collapseEmptyStrings(true);
498         command_wrappers->setVariable("ipv6", ipv6);
499 
500         QString at_var = address_table_re.cap(1);
501         QString at_file = rule->getStr("address_table_file").c_str();
502 
503         command_wrappers->setVariable("address_table_file", at_file);
504         command_wrappers->setVariable("address_table_var", at_var);
505         command_wrappers->setVariable("command", combined_command);
506         command_wrappers->setVariable("address_table", true);
507         command_wrappers->setVariable("wildcard_interface", false);
508         command_wrappers->setVariable("no_dyn_addr", false);
509         command_wrappers->setVariable("one_dyn_addr", false);
510         command_wrappers->setVariable("two_dyn_addr", false);
511 
512         combined_command = command_wrappers->expand();
513     }
514     return combined_command;
515 }
516 
printRunTimeWrappers(FWObject * rule,const string & command,bool ipv6)517 string OSConfigurator_linux24::printRunTimeWrappers(FWObject *rule,
518                                                     const string &command,
519                                                     bool ipv6)
520 {
521 /* if anywhere in command_line we used variable holding an address of
522  * dynamic interface (named $i_something) then we need to add this
523  * command with a check for the value of this variable. We execute
524  * iptables command only if the value is a non-empty string.
525  *
526  * bug #1851166: there could be two dynamic interfaces in the same
527  * rule.
528  */
529 
530     bool wildcard_interface = false;
531     QString combined_command;
532 
533     if (using_ipset)
534         combined_command = command.c_str();
535     else
536         combined_command = addressTableWrapper(rule, command.c_str(), ipv6);
537 
538     command_wrappers->clear();
539     command_wrappers->removeComments();
540     command_wrappers->collapseEmptyStrings(true);
541     command_wrappers->setVariable("ipv6", ipv6);
542 
543     command_wrappers->setVariable("address_table", false);
544 
545     QRegExp intf_re("\\$i_([^ :]+)");
546 
547     QStringList iface_names;
548     QStringList iface_vars;
549     int pos = -1;
550     while ((pos = intf_re.indexIn(combined_command, pos + 1)) > -1)
551     {
552         QString name = intf_re.cap(1);
553         int match_len = intf_re.matchedLength();
554         iface_names.push_back(name);
555         iface_vars.push_back("$i_" + name);
556         if (name.contains("*"))
557         {
558             wildcard_interface = true;
559             QString intf_family = name.section('*', 0, 0);
560             command_wrappers->setVariable("interface_family_name", intf_family);
561 
562             // replace $i_ppp* with $addr. This must match shell code
563             // in the configlet run_time_wrappers
564             combined_command.replace(pos, match_len, "$addr");
565 
566             break;
567         }
568     }
569 
570     bool no_wrapper = !wildcard_interface && iface_names.size() == 0;
571 
572     if (!no_wrapper)
573     {
574         QStringList command_lines =
575             QString(combined_command).split("\n", QString::SkipEmptyParts);
576         if (command_lines.size() > 1)
577         {
578             command_lines.push_front("{");
579             command_lines.push_back("}");
580         }
581         combined_command = command_lines.join("\n");
582     }
583 
584     command_wrappers->setVariable("no_wrapper", no_wrapper);
585     command_wrappers->setVariable("wildcard_interface", wildcard_interface);
586     command_wrappers->setVariable("one_dyn_addr",
587                                   !wildcard_interface && iface_names.size() == 1);
588     command_wrappers->setVariable("two_dyn_addr",
589                                   !wildcard_interface && iface_names.size() > 1);
590 
591     for (int idx=0; idx<iface_names.size(); ++idx)
592     {
593         QString intf_name = iface_names[idx];
594         //if (ipv6) intf_name += "_v6";
595         command_wrappers->setVariable(QString("intf_%1_var_name").arg(idx+1),
596                                       intf_name);
597     }
598 
599     command_wrappers->setVariable("command", combined_command);
600 
601     return command_wrappers->expand().toStdString() + "\n";
602 }
603 
printIPForwardingCommands()604 string OSConfigurator_linux24::printIPForwardingCommands()
605 {
606 /* Turn on packet forwarding if we have to */
607     // string os_family = Resources::os_res[fw->getStr("host_OS")]->
608     //     getResourceStr("/FWBuilderResources/Target/family");
609     FWOptions* options = fw->getOptionsObject();
610     Configlet ip_forwarding(fw, "linux24", "ip_forwarding");
611     ip_forwarding.removeComments();
612     ip_forwarding.collapseEmptyStrings(true);
613 
614     string s = options->getStr("linux24_ip_forward");
615     ip_forwarding.setVariable("ipv4", !s.empty());
616     ip_forwarding.setVariable("ipv4_forw", (s=="1" || s=="On" || s=="on")?1:0);
617 
618     s = options->getStr("linux24_ipv6_forward");
619     ip_forwarding.setVariable("ipv6", !s.empty());
620     ip_forwarding.setVariable("ipv6_forw", (s=="1" || s=="On" || s=="on")?1:0);
621 
622     return ip_forwarding.expand().toStdString();
623 }
624 
epilog()625 void OSConfigurator_linux24::epilog()
626 {
627 }
628 
629 
getGeneratedFiles() const630 map<string, string> OSConfigurator_linux24::getGeneratedFiles() const
631 {
632     map<string, string> files;
633     return files;
634 }
635