//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@>
int readether(std::vector<std::string> & argv, std::string & args)
{
 std::string localipfile    = "/var/smoothwall/red/local-ipaddress";
 std::string redfile        = "/var/smoothwall/red/iface";
 std::string etherfile      = "/var/smoothwall/ethernet/settings";
 std::string buildit        = "";
 char between[32]           = "";

 ConfigVAR   ether(etherfile);
 ConfigSTR   localip(localipfile);
 ConfigSTR   rediface(redfile);

 buildit += args + ",";
 if (args == "RED")
 {
  buildit += rediface.str() + ",";
  buildit += rediface.str() + ",";
  buildit += localip.str() + ",";
 }
 else
 {
  sprintf((char *)between, "%s%s", args.c_str(), "_DEV");
  if (ether[(const char *) between] == "") return 0;
  buildit += ether[(const char *) between] + ",";
  buildit += ether[(const char *) between] + ",";
  sprintf((char *)between, "%s%s", args.c_str(), "_ADDRESS");
  buildit += ether[(const char *) between] + ",";
 }
 sprintf((char *)between, "%s%s", args.c_str(), "_NETMASK");
 buildit += ether[(const char *) between] + ",";
 sprintf((char *)between, "%s%s", args.c_str(), "_BROADCAST");
 buildit += ether[(const char *) between] + ",";
 buildit += "on,on,,\n";
 argv.push_back(buildit);

return 0;
}
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@>
int ifaliasup(std::vector<std::string> & parameters, std::string & response)
{
 int error = 0;

 error = wrtaliases (response);
 if (error) return errrpt(response);

 std::vector<std::string> argv;

 std::string cmdprefix = "/var/smoothwall";
 std::string varfile     = cmdprefix + "/portfw/snort.var";
 std::string localipfile = "/var/smoothwall/red/local-ipaddress";
 std::string aliasfile   = cmdprefix + "/portfw/aliases";
 ConfigCSV   aliases(aliasfile);
 ConfigSTR   localip(localipfile);
 std::string::size_type n;
 char home_net[5000] = "";
 char * hnptr = home_net;
 FILE * varhandle;

 if (localip.str() == "")
 {
  response = "Abort, could not open red local IP file (" + localipfile + ")";
  return errrpt (response);
 }
 if (localip.str().find_first_not_of(IP_NUMBERS) != std::string::npos)
 {
  response = "Abort, bad local IP: " + localip.str();
  return errrpt (response);
 }
 std::string homenet = "var HOME_NET [" + localip.str();

 response = "Bringing alias interfaces up";
 error = errrpt(response);
 hnptr += sprintf(hnptr, "%s,", homenet.c_str());

 for (int line = aliases.first(); line == 0; line = aliases.next())
 {
  std::string f_color   = aliases[0];
  std::string f_ifalias = aliases[1];
  std::string f_ip      = aliases[3];
  std::string f_net     = aliases[4];
  std::string f_bcst    = aliases[5];

  if ((n = f_ifalias.find_first_of(":")) != std::string::npos && aliases[7] == "on")
  {
   // Add the alias to HOME_NET if it is enabled and we have room (with
   // 255 aliases maximum should be less than 4878 plus 28 chars at finish)

   if ((n = f_color.find("RED")) != std::string::npos)
    hnptr += sprintf(hnptr, "%s,", f_ip.c_str());


   errrpt("bringing up alias (" + f_ifalias + ")");

   if (f_ifalias.find_first_of("p") != std::string::npos)

    error += simplesecuresysteml("/sbin/ifconfig",f_ifalias.c_str(),f_ip.c_str(),
     "netmask",f_net.c_str(),"up",NULL);

   else

    error += simplesecuresysteml("/sbin/ifconfig",f_ifalias.c_str(),f_ip.c_str(),
     "netmask",f_net.c_str(),"broadcast",f_bcst.c_str(),"up",NULL);
  }
 }
 // backup one space to overwrite the trailing comma

 hnptr += sprintf(--hnptr, "]\n");

 if (!(varhandle = fopen(varfile.c_str(), "w")))
 {
  response = "Abort, could not create or open (" + varfile + ") file";
  return errrpt(response);
 }
 fputs((char*) home_net, varhandle);
 fclose(varhandle);

 errrpt("NOTE:  snort should be restarted manually to update its HOME_NET value");
 errrpt("NOTE:  /etc/snort.conf can be further customized for each scenario");

 response = "Successfully brought up alias interfaces.";
 if (error) response = "Abort while bringing up alias interfaces";

 return errrpt(response);
}
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@>
int set_portfw(std::vector<std::string> & parameters, std::string & response)
{
 int error = 0;
 std::string::size_type n;
 std::string::size_type p;
 std::vector<std::string>ipb;

 std::string localipfile = "/var/smoothwall/red/local-ipaddress";
 std::string ifacefile = "/var/smoothwall/red/iface";
 std::string cmdprefix = "/var/smoothwall";
 std::string configfile = cmdprefix + "/portfw/config";
 std::string aliasfile = cmdprefix + "/portfw/aliases";
 std::string sncheckfile = cmdprefix + "/portfw/subcheck";
 ConfigSTR   localip(localipfile);
 ConfigSTR   red_iface(ifacefile);
 ConfigCSV   fwdconf(configfile);
 ConfigCSV   aliases(aliasfile);
 ConfigVAR   subnetcheck(sncheckfile);

 std::string greencheck  = subnetcheck["GREEN"];
 std::string purplecheck = subnetcheck["PURPLE"];
 std::string orangecheck = subnetcheck["ORANGE"];

 // preset the response to a success, changed only on error, always return zero

 response = "Port forwarding rules set";

 if (localip.str() == "")
 {
  response = "Abort, could not open red local IP file (" + localipfile + ")";
  return errrpt (response);
 }
 if (localip.str().find_first_not_of(IP_NUMBERS) != std::string::npos)
 {
  response = "Abort, bad local IP: " + localip.str();
  return errrpt (response);
 }
 if (red_iface.str() == "")
 {
  response = "Abort, could not open red interface file (" + ifacefile + ")";
  return errrpt (response);
 }
 if (red_iface.str().find_first_not_of(INTERFACE) != std::string::npos)
 {
  response = "Abort, bad red interface specifier: " + red_iface.str();
  return errrpt (response);
 }
 std::string red_if      = red_iface.str();
 std::string fwdest_out  = "";
 std::string dest_out    = "";
 std::string ifc_in_out  = "";
 std::string ifc_out_out = "";
 std::string fwdportdest = "";
 std::string srcipmac_out= "";
 std::string dport_out   = "";
 std::string fwdport_out = "";
 std::string prot_out    = "";
 std::string dnat_out    = "";
 std::string tgt_out     = "";
 std::string in_dest     = "";
 bool bounce_type        = false;
 bool forwarding         = false;
 bool translating        = false;
 bool negated_source     = false;
 std::string temp_source = "";
 std::string internal_if = "";
 std::string conn_green  = "0xD0000000";
 std::string conn_purple = "0xE0000000";
 std::string conn_orange = "0xF0000000";
 std::string green_if    = "";
 std::string green_ifip  = "";
 std::string orange_if   = "";
 std::string orange_ifip = "";
 std::string purple_if   = "";
 std::string purple_ifip = "";
 /*
 The mark_mask value can only be used if we switch to CONNMARK tracking
 std::string mark_mask   = "0xFFF00000/";
 //=============================================================================>
 // We use the upper three nybbles of the available CMARK sequence numbers for
 // identifying the CMARKs associated with Full Firewall Control.  Any other
 // applications using CMARKs must be aware of this, always using a CMARK mask
 // that is not greater than 0x000FFFFF.  Available only if we use CONNMARK
 //=============================================================================>
 */
 rmdupes (ipb, "iptables -t filter -F portfwf");  // filtering rules  (moved stk)
 rmdupes (ipb, "iptables -t nat -F portfw");      // DNAT forwarding        (stk)
 rmdupes (ipb, "iptables -t mangle -F portfwb");  // MARK bounce & OMask    (stk)
 rmdupes (ipb, "iptables -t nat -F portfw_post"); // SNAT bounce & OMask    (add)
 rmdupes (ipb, "iptables -t filter -F portfwi");  // filter rules for INPUT (add)
 rmdupes (ipb, "iptables -t filter -F subnetchk");// filter rules FOR/INPUT (add)

 // ============================================================================>
 // we allow masking outbound to a red alias by having an association in
 // the alias file between a single internal IP and the alias interface
 // ============================================================================>
 // Here we find the internal interfaces for possible bouncing and create the
 // rules for masking outbounds to alias interfaces as we read the alias file

 unsigned int mark_seq = 0x800;

 for (int line = aliases.first(); line == 0; line = aliases.next())
 {
  char conn_mark[15] = "";

  const std::string & f_ifcolor   = aliases[0];
  const std::string & f_ifalias   = aliases[1];
  const std::string & f_realif    = aliases[2];
  const std::string & f_ipaddress = aliases[3];
  const std::string & f_addmask   = aliases[4];
  const std::string & f_enabled   = aliases[7];
  const std::string & f_mask2add  = aliases[9];
  std::string scprefixf = "iptables -t filter -A";
  std::string sclogpre = " -j LOG --log-prefix ..FFC..not.";
  std::string sclogpost = ".subnet..";
  std::string sclogrej = " -j REJECT";

  //  Allow DHCP to bypass subnet checking
  rmdupes (ipb, scprefixf + " subnetchk -p udp --dport 67 -j RETURN");
  rmdupes (ipb, scprefixf + " portfwi -j subnetchk");
  rmdupes (ipb, scprefixf + " portfwf -j subnetchk");

  //============================================================================>
  //  log and reject any packets with a source that is not in the correct
  //  subnet for the interface that received them
  //===>>  To disable:  set "(GREEN|PURPLE|ORANGE)=off" in the "sncheckfile"

  if (f_ifcolor == "GREEN")
  {
   green_if = f_realif;
   green_ifip = f_ipaddress;
   if (greencheck != "off")
   {
    char cidr[5] = "";
    sprintf((char*) cidr, "/%d", snet2cidr(f_addmask));

    std::string scpostfixl = (" -i " + green_if + " ! -s " + green_ifip + cidr +
     sclogpre + f_ifcolor + sclogpost);
    std::string scpostfixr = (" -i " + green_if + " ! -s " + green_ifip + cidr +
     sclogrej);

    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl);
    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr);
   }
  }
  if (f_ifcolor == "ORANGE")
  {
   orange_if = f_realif;
   orange_ifip = f_ipaddress;
   if (orangecheck != "off")
   {
    char cidr[5] = "";
    sprintf((char*) cidr, "/%d", snet2cidr(f_addmask));

    std::string scpostfixl = (" -i " + orange_if + " ! -s " + orange_ifip + cidr +
     sclogpre + f_ifcolor + sclogpost);
    std::string scpostfixr = (" -i " + orange_if + " ! -s " + orange_ifip + cidr +
     sclogrej);

    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl);
    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr);
   }
  }
  if (f_ifcolor == "PURPLE")
  {
   purple_if = f_realif;
   purple_ifip = f_ipaddress;
   if (purplecheck != "off")
   {
    char cidr[5] = "";
    sprintf((char*) cidr, "/%d", snet2cidr(f_addmask));

    std::string scpostfixl = (" -i " + purple_if + " ! -s " + purple_ifip + cidr +
     sclogpre + f_ifcolor + sclogpost);
    std::string scpostfixr = (" -i " + purple_if + " ! -s " + purple_ifip + cidr +
     sclogrej);

    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl);
    rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr);
   }
  }
  if (f_mask2add != "" && f_mask2add.find_first_of("/") == std::string::npos &&
   f_ifalias.find_first_of(":") != std::string::npos && f_enabled == "on")

  //============================================================================>
  // Make sure we have an alias interface and a single IP to mask
  {
   sprintf((char*) conn_mark, "%#010x", (++mark_seq) * 0x100000);
   conn_mark[10] = 0;

   rmdupes (ipb, "iptables -t mangle -A portfwb -s " + f_mask2add +
    " -j MARK --set-mark " + conn_mark);

   rmdupes (ipb, "iptables -t nat -A portfw_post -o " + red_if + " -s " + f_mask2add +
    " -m mark --mark " + conn_mark + " -j SNAT --to-source " + f_ipaddress);
  }
  if (mark_seq > 0x8FF)
  {
   response = "Abort, more than 255 aliases not supported, reduce alias count.";
   return errrpt (response);
  }
  if (error)
  {
   response = "Abort in alias file for " + f_ifalias + " interface.";
   return errrpt (response);
  }
 }//     <<== End of reading "aliasfile"

 //=============================================================================>
 // This is to clean up any previously entered jumps around the proxies, then
 // we set the jumps around the proxies for any outbound masking to an alias

 std::string proxy_jmph = "iptables -t nat ";
 std::string proxy_jmpt = " -m mark --mark 0x80000000/0x80000000 -j RETURN";

 // the match mark mask does not correctly mask for some reason
 // the position of flag and mask might be reversed

 if (chkproxy())
 {
  rmdupes (ipb, proxy_jmph + "-D jmpim" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-D jmpp3scan" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-D jmpsip" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-D jmpsquid" + proxy_jmpt);
 }

 if (mark_seq > 0x800)
 {
  rmdupes (ipb, proxy_jmph + "-I jmpim" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-I jmpp3scan" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-I jmpsip" + proxy_jmpt);
  rmdupes (ipb, proxy_jmph + "-I jmpsquid" + proxy_jmpt);
 }
 //=============================================================================>
 // Read the rules, in sequence from "configfile" and build

 for (int line = fwdconf.first(); line == 0; line = fwdconf.next())
 {
  const std::string & f_input   = fwdconf[1];
  const std::string & f_source  = fwdconf[2];
  const std::string & f_dport   = fwdconf[3];
  const std::string & f_output  = fwdconf[4];
  const std::string & f_fwdest  = fwdconf[5];
  const std::string & f_fwdport = fwdconf[6];
  const std::string & f_proto   = fwdconf[7];
  const std::string & f_action  = fwdconf[8];
  const std::string & f_enabled = fwdconf[9];

  if (f_input.find_first_not_of(INTERFACE) != std::string::npos &&
   (f_input.find_first_not_of(INTERFACE_ALIAS) != std::string::npos) &&
    f_input != "any")
  {
   response = "Abort, bad input interface: (" + f_input + ") rule number " +
    fwdconf[0];
   return errrpt (response);
  }
  if (f_output.find_first_not_of(INTERFACE) != std::string::npos &&
   (f_output.find_first_not_of(INTERFACE_ALIAS) != std::string::npos) &&
    f_output != "any")
  {
   response = "Abort, bad output interface: " + f_output + " rule number " +
    fwdconf[0];
   return errrpt (response);
  }
  if (f_proto.find_first_not_of(NUMBERS) != std::string::npos &&
   f_proto != "all")
  {
   response = "Abort, bad protocol: (" + f_proto + ") rule number " + fwdconf[0];
   return errrpt (response);
  }
  if (f_dport.find_first_not_of(NUMBERS_COLON) != std::string::npos)
  {
   response = "Abort, bad initial destination port: (" + f_dport +
    ") rule number " + fwdconf[0];
   return errrpt (response);
  }
  // First operation is to remove negation, if present

  negated_source = false;
  if ((p = f_source.find_first_of("! ")) != std::string::npos &&
   (n = f_source.find_first_not_of("! ")) != std::string::npos)
  {
     negated_source = true;
     temp_source = f_source;
     temp_source = temp_source.erase(p, n - p);
  }
  else temp_source = f_source;

  if (temp_source.find_first_not_of(IP_NUMBERS) != std::string::npos &&
   temp_source.find_first_not_of(MAC_HEX) != std::string::npos)
  {
   response = "Abort, bad source IP or MAC: (" + f_source + ") rule number " +
    fwdconf[0];
   return errrpt (response);
  }
  if (f_fwdest.find_first_not_of(IP_NUMBERS) != std::string::npos)
  {
   response = "Abort, bad new destination IP: (" + f_fwdest + ") rule number " +
    fwdconf[0];
   return errrpt (response);
  }
  if (f_fwdport.find_first_not_of(NUMBERS_COLON) != std::string::npos)
  {
   response = "Abort, bad new destination port: (" + f_fwdport +
    ") rule number " + fwdconf[0];
   return errrpt (response);
  }
  if (f_action != "REJECT" && f_action != "RETURN" && f_action != "ACCEPT" &&
   f_action  != "DROP"   &&	f_action != "LOG")
  {
   response = "Abort, bad action: (" + f_action + ") rule number " + fwdconf[0];
   return errrpt (response);
  }
  if (f_enabled == "on")
  {
   // ==========================================================================>
   // we allow red bouncing by specifying that it comes from * interface
   // because bouncing requires that DNAT and SNAT be done on the packets
   // specifying an interface on bounces is not possible, the source is the
   // destination for bounces, if the source must be limited on bounces,
   // use an IP limitation
   // ==========================================================================>
   // Here we create the source strings, or leave null if unused

   forwarding = false;
   in_dest = "";
   if (f_input.find(red_if) != std::string::npos)
   {
    if (f_proto == "1" || f_proto == "6" || f_proto == "17" ||
     f_proto == "47" || f_proto == "50" || f_proto == "51")
    {
     forwarding = true;

     // ICMP:1 TCP:6 UDP:17 GRE:47 ESP:50 AH:51   <---Forwarded protocols

     in_dest = localip.str();

     // default IP for the actual red interface, changed only for aliases
     // If it is an alias

     if (f_input.find(":") != std::string::npos)
     {
      for (int line = aliases.first(); line == 0; line = aliases.next())

      // forwarding from the red interface we need to find the IP
      {
       const std::string & f_ifalias = aliases[1];
       const std::string & f_ipaddress = aliases[3];

       if ((f_input == f_ifalias  && aliases[7] == "on"))
        in_dest = f_ipaddress;
      }
     }
     if (in_dest.find_first_not_of(IP_NUMBERS) != std::string::npos &&
      in_dest.find_first_of("/") != std::string::npos)
     {
      response = "Abort, could not find match for interface (" + f_input +
       ") and IP (" + in_dest +
        ") to construct a forwarding rule in rule number " + fwdconf[0];
      return errrpt (response);
     }
    }  //  <<== End of protocol
   }  //  <<== End of Red IF

   ifc_in_out = "";
   if (f_input != "any" && ! forwarding)

   // If it is not "any" and not being forwarded set the input interface
   {
    ifc_in_out = f_input;

    // If it is an alias interface, truncate the string starting with the colon

    if ((n = ifc_in_out.find_first_of(":")) != std::string::npos)
     ifc_in_out.erase(n, 4);

    ifc_in_out = " -i " + ifc_in_out;
   }
   ifc_out_out = "";
   if (f_output != "any" && f_output != "")
   {
    ifc_out_out = f_output;

    if ((n = ifc_out_out.find_first_of(":")) != std::string::npos)
     ifc_out_out.erase(n, 4);

    ifc_out_out = " -o " + ifc_out_out;
   }
   prot_out = "";
   if (f_proto != "all" && f_proto != "") prot_out = " -p " + f_proto;

   dest_out = "";
   if (in_dest != "") dest_out = " -d " + in_dest;

   dport_out = "";
   if (f_dport !=  "0" && f_dport !=  "") dport_out = " --dport " + f_dport;

   translating = false;
   fwdport_out = "";
   fwdportdest = "";
   if (f_fwdport !=  "0" && f_fwdport !=  "")
   {
    translating = true;
    fwdport_out = " --dport " + f_fwdport;
    fwdportdest = f_fwdport;

    if ((n = fwdportdest.find_first_of(":")) != std::string::npos)
     fwdportdest.replace(n, 1, "-");

    fwdportdest = ":" + fwdportdest;
   }

   fwdest_out = "";
   dnat_out = "";
   if (translating || forwarding)
   {
    if (f_fwdest != "" &&
      f_fwdest.find_first_of("/") == std::string::npos)

    // an IP is being forwarded, but we must have a destination IP to
    // forward to for DNAT to be sensible
    {
     fwdest_out = " -d " + f_fwdest;
     dnat_out = " -j DNAT --to-destination " + f_fwdest + fwdportdest;
    }
    // If we expected to build a DNAT rule and failed, the IP is not singular

    if (dnat_out == "")
    {
     response = "Abort, bad new destination IP (" + f_fwdest +
      "), must be single IP in rule number " + fwdconf[0];
     return errrpt (response);
    }
    // translation requires the same IP in the DNAT initial destination

    if (! forwarding) dest_out = fwdest_out;
   }
   srcipmac_out = "";
   if (temp_source.find_first_not_of(IP_NUMBERS) == std::string::npos)
   {
    srcipmac_out = " -s " + temp_source;
   }
   if (temp_source.find_first_not_of(MAC_HEX) == std::string::npos)
   {
    srcipmac_out = " -m mac --mac-source " + temp_source;
   }
    // must be a space between "!" and the descriptor
    if (negated_source) srcipmac_out = " ! " + srcipmac_out;

   tgt_out = " -j " + f_action;
   if (f_action == "LOG") tgt_out = " -j LOG --log-prefix ..FFC..";

   // if we aren't going to DNAT we still need some information in portfwf

   if (! translating && dport_out != "") fwdport_out = dport_out;

   if (dnat_out == "" && f_fwdest != "") fwdest_out = " -d " + f_fwdest;

   // ==========================================================================>
   // Here we get down to the business of creating the rules from the strings

   if (forwarding || translating) rmdupes (ipb, "iptables -t nat -A portfw " +
    ifc_in_out + prot_out + srcipmac_out + dest_out + dport_out + dnat_out);

   rmdupes (ipb, "iptables -t filter -A portfwf -m state --state NEW" +
    ifc_out_out + prot_out + srcipmac_out + fwdest_out +
     fwdport_out + tgt_out);

   // In the INPUT chain we should not ACCEPT since EXTACCESS should be the
   // source for that type of rule, and only process rules that are not
   // forwarding or translating rules, meaning no specific output interface

   if (tgt_out == " -j ACCEPT") tgt_out = " -j RETURN";

   // Note: If the destination interface is specified then we don't create
   // a rule.  This allows the proxies to bypass a block rule for outbounds
   // which may be blocked by an additional specific rule with the Any
   // interface specified.  Another option explored was to skip only ACCEPT
   // rules, but that has limited usability as well.

   if (ifc_out_out == "")
    rmdupes (ipb, "iptables -t filter -A portfwi -m state --state NEW" +
     ifc_in_out + prot_out + srcipmac_out + dport_out + tgt_out);

   // ==========================================================================>
   // Here we create rules for bouncing if the input interface is null and
   // there has been a DNAT for the red interface, we skip translating DNAT

   if (forwarding)
   {
    std::string forward_pre = "iptables -t mangle -A portfwb -i ";
    std::string forward_post = " -j MARK --set-mark ";

    if (green_if  != "") rmdupes (ipb, forward_pre + green_if  + dest_out +
     forward_post +  conn_green);

    if (purple_if != "") rmdupes (ipb, forward_pre + purple_if + dest_out +
     forward_post + conn_purple);

    if (orange_if != "") rmdupes (ipb, forward_pre + orange_if + dest_out +
     forward_post + conn_orange);

    bounce_type = true;
   }

  }//   <<==== End of enabled

 }//   <<==== End of reading portfw/config file

 //=============================================================================>
 // The rules have been created, now we need to allow bounces, if we are doing
 // any portforwarding that allows bouncing

 if (bounce_type)
 {
  // We only need to SNAT those packets that came in the same interface that
  // they are going out on to ensure the return path is through the interface

  std::string pfw_post_pre = "iptables -t nat -A portfw_post -m mark --mark ";
  std::string pfw_post_post = " -j SNAT --to-source ";

  if (green_if != "")
   rmdupes (ipb, pfw_post_pre + conn_green  + " -o " + green_if  + pfw_post_post +
    green_ifip);

  if (purple_if != "")
   rmdupes (ipb, pfw_post_pre + conn_purple + " -o " + purple_if + pfw_post_post +
    purple_ifip);

  if (orange_if != "")
   rmdupes (ipb, pfw_post_pre + conn_orange + " -o " + orange_if + pfw_post_post +
    orange_ifip);
 }
 //=============================================================================>
 // Pass the built up vector of strings to ipbatch to build IPTables entries

 error = ipbatch(ipb);

 if (error) response = "Abort flushing rules to IPTables";
 return errrpt (response);
}
Example #4
0
int set_incoming(std::vector<std::string> & parameters, std::string & response)
{
	int error = 0;

	std::string::size_type n;
	std::vector<std::string>ipbfilter;
	std::vector<std::string>ipbnat;
	std::vector<std::string>ipbmangle;

	ConfigSTR localip("/var/smoothwall/red/local-ipaddress");
	ConfigSTR iface("/var/smoothwall/red/iface");
	ConfigCSV fwdfile("/var/smoothwall/portfw/config");
	ConfigVAR ethernet("/var/smoothwall/ethernet/settings");

	if ((error = (localip.str() == "")))
	{
		response = "Couldn't open local IP file";
		return error;
	}
	// carry on
	if ((n = localip.str().find_first_not_of(IP_NUMBERS)) != std::string::npos) 
	{
		// illegal characters
		response = "Bad local IP: " + localip.str();
		error = 1;
		return error;
	}
	if ((error = (iface.str() == "")))
	{
		response = "Couldn't open iface file";
		return error;
	}
	// carry on
	if ((n = iface.str().find_first_not_of(LETTERS_NUMBERS)) != std::string::npos) 
	{
		// illegal characters
		response = "Bad iface: " + iface.str();
		error = 1;
		return error;
	}

	ipbfilter.push_back("iptables -t filter -F portfwf");
	ipbnat.push_back("iptables -t nat -F portfw");
	ipbmangle.push_back("iptables -t mangle -F portfwb");

	// iterate the CSV
	for (int line = fwdfile.first(); line == 0; line = fwdfile.next())
	{
		std::string remdouble;
		const std::string & protocol = fwdfile[0];
		const std::string & extip = fwdfile[1];
		const std::string & locport = fwdfile[2];
		const std::string & remip = fwdfile[3];

		// this last one want to change maybe
		std::string remport = fwdfile[4];
		const std::string & enabled = fwdfile[5];
		if ((n = protocol.find_first_not_of(LETTERS)) != std::string::npos)
		{
			response = "Bad protocol: " + protocol;
			error = 1;
			return error;
		}
		if ((n = extip.find_first_not_of(IP_NUMBERS)) != std::string::npos)
		{
			response = "Bad external IP: " + extip;
			error = 1;
			return error;
		}
		if ((n = locport.find_first_not_of(NUMBERS_COLON)) != std::string::npos)
		{
			response = "Bad local port: " + locport;
			error = 1;
			return error;
		}
		if ((n = remip.find_first_not_of(IP_NUMBERS)) != std::string::npos)
		{
			response = "Bad remote IP: " + remip;
			error = 1;
			return error;
		}
		if ((n = remport.find_first_not_of(NUMBERS)) != std::string::npos)
		{
			response = "Bad remote port: " + remport;
			error = 1;
			return error;
		}

		if (enabled == "on")
		{
			if (remport == "0")
				remport = locport;
			// if locport does not have : or originally remport not zero 
			if(locport.find_first_of(":") == std::string::npos || fwdfile[4] != "0")
				remdouble = remip + ":" + remport;
			else 
				remdouble = remip;

			ipbfilter.push_back("iptables -t filter -A portfwf -m state --state NEW -p " + protocol +
				" -s " + extip +
				" -d " + remip +
				" --dport " + remport + " -j ACCEPT");
			ipbnat.push_back("iptables -t nat -A portfw -p " + protocol +
				" -s " + extip +  
				" -d " + localip.str() +  			
				" --dport " + locport + " -j DNAT --to " + remdouble);
		}
	}

	/* Rules to detect bouncing port forwarding */
	int mark = 0;
	std::string insideinterface;
	while (mark++ < 3)
	{
		switch (mark)
		{
			case 1: insideinterface = ethernet["GREEN_DEV"];  break;
			case 2: insideinterface = ethernet["ORANGE_DEV"]; break;
			case 3: insideinterface = ethernet["PURPLE_DEV"]; break;
			default: break;
		}

		if (insideinterface != "")
		{
			ipbmangle.push_back("iptables -t mangle -A portfwb -i " + insideinterface +
				" -d " + localip.str() + " -j MARK --set-mark " + stringprintf("%d", mark));
		}
	}

	error = ipbatch(ipbfilter);
	if (error)
	{
		response = "ipbatch failure (filter)";
		return error;
	}

	error = ipbatch(ipbnat);
	if (error)
	{
		response = "ipbatch failure (nat)";
		return error;
	}
	
	error = ipbatch(ipbmangle);
	if (error)
	{
		response = "ipbatch failure (mangle)";
		return error;
	}
	
	response = "Portfw rules set";

	return (error);
}