/**
 * Copyright 2004, Novell, Inc.  All rights reserved.
 *
 * File:	firewall/cmdline.ycp
 * Package:	Firewall configuration
 * Summary:	Command Line for YaST2 Firewall
 * Authors:	Lukas Ocilka <locilka@suse.cz>
 *
 * $Id: cmdline.ycp 21778 2005-02-21 15:16:36Z locilka $
 */

{
    textdomain "firewall";

    import "CommandLine";
    import "SuSEFirewall";
    import "SuSEFirewallServices";
    import "Mode";
    import "Report";
    import "String";

    include "firewall/summary.ycp";
    include "firewall/generalfunctions.ycp";
    
    // simple_text variable from summary.ycp
    simple_text = true;

    list <string> CommaSeparatedList(any comma_separated_string) {
	return splitstring((string) comma_separated_string, ",");
    }

    /**
     * Function checks zone string for existency
     *
     * @param	string zone
     * @param	boolean optional, true=is optional, false=has to be set
     * @return	boolean if zone exists or not set if optional
     */
    boolean CheckZone (string zone, boolean optional) {
	// any zone defined
	if (zone!="" && zone!=nil) {
	    // unknown zone
	    if (!contains(SuSEFirewall::GetKnownFirewallZones(), zone)) {
		// TRANSLATORS: CommandLine error, %1 is a firewall zone shortcut
		CommandLine::Error(sformat(_("Unknown zone '%1'"), zone));
		return false;
	    // defined, known zone
	    } else {
		return true;
	    }
	// no zone defined
	} else {
	    // not needed, OK
	    if (optional) return true;

	    // TRANSLATORS: CommandLine error, %1 is needed parameter name
	    CommandLine::Error(sformat(_("Parameter '%1' must be set"), "zone"));
	    return false;
	}
    }

    void ListFirewallZones () {
	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Listing Known Firewall Zones"),0));
	CommandLine::Print("");

	list <list <string> > table_items = [];
	foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
	    table_items = add(table_items, [ zone, SuSEFirewall::GetZoneFullName(zone) ]);
	});
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Shortcut"),
		// TRANSLATORS: CommandLine table header item
		_("Zone Name")
	    ],
	    table_items,
	    $[]
	));

	CommandLine::Print("");
    }

    boolean FWCMDZones (map options) {
	// listing known zones
	if (options["list"]:nil != nil) {
	     ListFirewallZones();
	}

	// Do not call Write()
	return false;
    }

    boolean FWCMDSummary (map options) {
	// printing summary

	// no zone => all zones
	string for_zone = (string) options["zone"]:nil;
	list <string> for_zones = [];
	if (for_zone!=nil) {
	    if (!CheckZone(for_zone, false)) {
		return false;
	    } else {
		for_zones = [for_zone];
	    }
	}

	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Summary"), 0));
	CommandLine::Print("");
	CommandLine::Print(InitBoxSummary(for_zones));

	// Do not call Write()
	return false;
    }

    boolean FWCMDStartup (map options) {
	if (options["atboot"]:nil!=nil && options["manual"]:nil!=nil) {
	    // TRANSLATORS: CommandLine error message
	    CommandLine::Error(_("Only one parameter is allowed"));
	} else if (options["atboot"]:nil!=nil) {
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Start-Up"), 0));
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine progress information
	    CommandLine::Print(_("Enabling firewall in the boot process..."));
	    CommandLine::Print("");
	    SuSEFirewall::SetEnableService(true);
	} else if (options["manual"]:nil!=nil) {
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Start-Up"), 0));
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine progress information
	    CommandLine::Print(_("Removing firewall from the boot process..."));
	    CommandLine::Print("");
	    SuSEFirewall::SetEnableService(false);
	} else if (options["show"]:nil!=nil) {
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Start-Up"), 0));
	    CommandLine::Print("");
	    if (SuSEFirewall::GetEnableService()) {
		// TRANSLATORS: CommandLine informative text
		CommandLine::Print(_("Firewall is enabled in the boot process"));
	    } else {
		// TRANSLATORS: CommandLine informative text
		CommandLine::Print(_("Firewall needs manual starting"));
	    }
	    CommandLine::Print("");
	}

	return true;
    }

    boolean FWCMDInterfaces (map options) {
	list <string> unassigned_interfaces = [];
	map <string, map <string, string> > interfaces = $[];
	foreach (map <string, string> interface, SuSEFirewall::GetAllKnownInterfaces(), {
	    interfaces[interface["id"]:""] = interface;
	    if (interface["zone"]:nil==nil) {
		unassigned_interfaces = add(unassigned_interfaces, interface["id"]:nil);
	    }
	});
	string for_zone = (string) options["zone"]:nil;
	if (!CheckZone(for_zone, true)) return false;

	CommandLine::Print("");
	// creating current configuration list
	if (options["show"]:nil!=nil) {
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Network Interfaces in Firewall Zones"),0));
	    CommandLine::Print("");

	    list <list <string> > table_items = [];
	    map <string, list <string> > special_interfaces = $[];
	    foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
		// for_zone defined but it is not current zone
		if (for_zone!=nil && for_zone!=zone) return;
	    
		foreach (string interface, SuSEFirewall::GetInterfacesInZone(zone), {
		    table_items = add(table_items, [zone, interface, interfaces[interface,"name"]:""]);
		});
		foreach (string spec_int, SuSEFirewall::GetSpecialInterfacesInZone(zone), {
		    // TRANSLATORS: CommandLine table item (unknown/special string/interface)
		    table_items = add(table_items, [zone, spec_int, _("Special Firewall String")]);
		});
	    });
	    // print unassigned only in general view
	    if (for_zone==nil && size(unassigned_interfaces)>0) {
		foreach (string interface, unassigned_interfaces, {
		    table_items = add(table_items, ["---", interface, interfaces[interface,"name"]:""]);
		});
	    }
	    CommandLine::Print(String::TextTable(
		[
		    // TRANSLATORS: CommandLine table header item
		    _("Zone"),
		    // TRANSLATORS: CommandLine table header item
		    _("Interface"),
		    // TRANSLATORS: CommandLine table header item
		    _("Device Name")
		],
		table_items,
		$[]
	    ));
	} else if (options["add"]:nil!=nil) {
	    string interface = (string) options["interface"]:nil;
	    if (interface==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "interface"));
		return false;
	    }
	    if (for_zone==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "zone"));
		return false;
	    }
	    // unknown interface
	    if (interfaces[interface]:$[]==$[]) {
		// TRANSLATORS: CommandLine progress information, %1 is the special string, %2 is the zone name
		CommandLine::Print(sformat(_("Adding special string '%1' into zone '%2'..."), interface, for_zone));
		SuSEFirewall::AddSpecialInterfaceIntoZone(interface, for_zone);
	    } else {
		// TRANSLATORS: CommandLine progress information, %1 is the network interface name, %2 is the zone name
		CommandLine::Print(sformat(_("Adding interface '%1' into zone '%2'..."), interface, for_zone));
		SuSEFirewall::AddInterfaceIntoZone(interface, for_zone);
	    }
	} if (options["remove"]:nil!=nil) {
	    string interface = (string) options["interface"]:nil;
	    if (interface==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "interface"));
		return false;
	    }
	    if (for_zone==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "zone"));
		return false;
	    }
	    // unknown interface
	    if (interfaces[interface]:$[]==$[]) {
		// TRANSLATORS: CommandLine progress information, %1 is the special string, %2 is the zone name
		CommandLine::Print(sformat(_("Removing special string '%1' from zone '%2'..."), interface, for_zone));
		SuSEFirewall::RemoveSpecialInterfaceFromZone(interface, for_zone);
	    } else {
		// TRANSLATORS: CommandLine progress information, %1 is the network interface name, %2 is the zone name
		CommandLine::Print(sformat(_("Removing interface '%1' from zone '%2'..."), interface, for_zone));
		SuSEFirewall::RemoveInterfaceFromZone(interface, for_zone);
	    }
	}
	CommandLine::Print("");

	return true;
    }

    boolean FWCMDLogging (map options) {
	map <string, string> logging_meaning = $[
	    // TRANSLATORS: CommandLine table item
	    "ALL" : _("Log All"),
	    // TRANSLATORS: CommandLine table item
	    "CRIT" : _("Log Only Critical"),
	    // TRANSLATORS: CommandLine table item
	    "NONE" : _("Do Not Log Any"),
	];

	if (options["show"]:nil!=nil) {
	    string log_accepted = SuSEFirewall::GetLoggingSettings("ACCEPT");
	    string log_nonaccepted = SuSEFirewall::GetLoggingSettings("DROP");

	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Global Logging Settings"),0));
	    CommandLine::Print("");

	    CommandLine::Print(String::TextTable(
		[
		    // TRANSLATORS: CommandLine table header item
		    _("Rule Type"),
		    // TRANSLATORS: CommandLine table header item
		    _("Value"), _("Logging Level")
		],
		[
		    // TRANSLATORS: CommandLine table item
		    [ _("Accepted"),	 tolower(log_accepted),	   logging_meaning[log_accepted]:"Software Error"    ],
		    // TRANSLATORS: CommandLine table item
		    [ _("Not Accepted"), tolower(log_nonaccepted), logging_meaning[log_nonaccepted]:"Software Error" ]
		],
		$[]
	    ));
	    CommandLine::Print("");

	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Logging Broadcast Packets"),0));
	    CommandLine::Print("");

	    list <list <string> > table_items = [];
	    foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
		table_items = add(table_items, [
		    zone,
		    SuSEFirewall::GetZoneFullName(zone),
		    (SuSEFirewall::GetIgnoreLoggingBroadcast(zone)=="yes" ?
			// TRANSLATORS: CommandLine table item
			_("Logging Enabled")
			:
			// TRANSLATORS: CommandLine table item
			_("Logging Disabled")
		    )
		]);
	    });
	    CommandLine::Print(String::TextTable(
		[
		    // TRANSLATORS: CommandLine table header item
		    _("Short"),
		    // TRANSLATORS: CommandLine table header item
		    _("Zone Name"),
		    // TRANSLATORS: CommandLine table header item
		    _("Logging Status")
		],
		table_items,
		$[]
	    ));
	    CommandLine::Print("");

	    return false;
	} else if (options["set"]:nil!=nil) {
	    list <string> possible_levels = [ "all", "crit", "none" ];
	    if (options["accepted"]:nil!=nil) {
		string value = tolower((string) options["accepted"]:nil);
		if (!contains(possible_levels, value)) {
		    // TRANSLATORS: CommandLine error message, %1 is an option value, %2 is an option name
		    CommandLine::Error(sformat(_("Value '%1' is not allowed for option '%2'."), options["accepted"]:nil, "accepted"));
		    return false;
		}
		SuSEFirewall::SetLoggingSettings("ACCEPT",toupper(value));
	    }
	    if (options["nonaccepted"]:nil!=nil) {
		string value = tolower((string) options["nonaccepted"]:nil);
		if (!contains(possible_levels, value)) {
		    // TRANSLATORS: CommandLine error message, %1 is an option value, %2 is an option name
		    CommandLine::Error(sformat(_("Value '%1' is not allowed for option '%2'."), options["nonaccepted"]:nil, "nonaccepted"));
		    return false;
		}
		SuSEFirewall::SetLoggingSettings("DROP",toupper(value));
	    }
	    if (options["logbroadcast"]:nil!=nil) {
		list <string> zones_to_setup = SuSEFirewall::GetKnownFirewallZones();
		// zone defined
		string zone = (string) options["zone"]:nil;
		// zone is defined
		if (zone!=nil) {
		    // defined, but wrong
		    if (!CheckZone(zone, false)) {
			return false;
		    // defined well
		    } else {
			zones_to_setup = [ zone ];
		    }
		}

		string value = tolower((string) options["logbroadcast"]:nil);
		if (!contains(["yes", "no"], value)) {
		    // TRANSLATORS: CommandLine error message, %1 is an option value, %2 is an option name
		    CommandLine::Error(sformat(_("Value '%1' is not allowed for option '%2'."), options["logbroadcast"]:nil, "logbroadcast"));
		    return false;
		}
		
		foreach (string zone, zones_to_setup, {
		    SuSEFirewall::SetIgnoreLoggingBroadcast(zone, value);
		});
	    }

	    return true;
	}
    }

    boolean FWCMDBroadcast (map options) {
	if (options["show"]:nil!=nil) {
	    // all zones if no zone is defined
	    list <string> for_zones = SuSEFirewall::GetKnownFirewallZones();
	    string zone = (string) options["zone"]:"";
	    if (zone!="") {
		if (!CheckZone(zone, false)) {
		    return false;
		} else {
		    for_zones = [ zone ];
		}
	    }

	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Allowed Broadcast Ports"),0));
	    CommandLine::Print("");
	    list <list <string> > table_items = [];
	    map <string, list <string> > broadcast_ports = SuSEFirewall::GetBroadcastAllowedPorts();
	    foreach (string zone, for_zones, {
		string zone_name = SuSEFirewall::GetZoneFullName(zone);
		foreach (string port, broadcast_ports[zone]:[], {
		    table_items = add(table_items, [ zone, zone_name, port ]);
		});
	    });
	    CommandLine::Print(String::TextTable(
		[
		    // TRANSLATORS: CommandLine header item
		    _("Short"),
		    // TRANSLATORS: CommandLine header item
		    _("Zone Name"),
		    // TRANSLATORS: CommandLine header item
		    _("Port")
		],
		table_items,
		$[]
	    ));
	    CommandLine::Print("");

	    return false;
	} else if (options["add"]:nil!=nil && options["remove"]:nil!=nil) {
	    // TRANSLATORS: CommandLine error message
	    CommandLine::Error(_("Only one action command is allowed here."));
	    return false;
	} else if (options["add"]:nil!=nil || options["remove"]:nil!=nil) {
	    // undefined zone
	    if (options["zone"]:nil==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "zone"));
		return false;
	    }
	    // unknown zone
	    string zone = (string) options["zone"]:nil;
	    if (!CheckZone(zone, false)) {
		return false;
	    }

	    // undefined port
	    if (options["port"]:nil==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "port"));
		return false;
	    }

	    string todo = "";
	    if (options["add"]:nil!=nil) {
		todo = "add";
	    } else if (options["remove"]:nil!=nil) {
		todo = "remove";
	    }

	    map <string, list <string> > broadcast_ports = SuSEFirewall::GetBroadcastAllowedPorts();
	    foreach (string port, CommaSeparatedList(options["port"]:""), {
		if (todo == "add") {
		    broadcast_ports[zone] = toset(add(broadcast_ports[zone]:[], port));
		} else {
		    broadcast_ports[zone] = filter(string filter_port, broadcast_ports[zone]:[], {
			return filter_port != port;
		    });
		}
	    });

	    SuSEFirewall::SetBroadcastAllowedPorts(broadcast_ports);
	    return true;
	}

	return false;
    }

    void FWCMDServicesList() {
	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Defined Firewall Services"),0));
	list <list <string> > table_items = [];
	foreach (string service_id, string service_name, SuSEFirewallServices::GetSupportedServices(), {
	    table_items = add (table_items, [ service_id, service_name ]);
	});
	CommandLine::Print("");
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Id"),
		// TRANSLATORS: CommandLine table header item
		_("Service Name")
	    ],table_items,$[]
	));
	CommandLine::Print("");
    }

    void FWCMDServicesShow (list <string> for_zones, boolean detailed) {
	map <string, string> known_services = SuSEFirewallServices::GetSupportedServices();
	boolean protect_from_INT = SuSEFirewall::GetProtectFromInternalZone();

	map <string, string> detailed_def = $[
	    // TRANSLATORS: CommandLine table item
	    "tcp_ports"		: _("TCP Port"),
	    // TRANSLATORS: CommandLine table item
	    "udp_ports"		: _("UDP Port"),
	    // TRANSLATORS: CommandLine table item
	    "rpc_ports"		: _("RPC Port"),
	    // TRANSLATORS: CommandLine table item
	    "ip_protocols"	: _("IP Protocol"),
	];

	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Allowed Services in Zones"),0));
	CommandLine::Print("");
	list <list <string> > table_items = [];
	foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
	    if (!contains(for_zones, zone)) return;

	    if (zone=="INT" && protect_from_INT==false) {
		table_items = add (table_items, [
		    zone,
		    // TRANSLATORS: CommandLine table item (all firewall services are allowed in this zone)
		    "*" + _("All Services") + "*",
		    // TRANSLATORS: CommandLine table item (this zone is not protected at all)
		    "*" + _("Entire Zone Unprotected") + "*"
		]);
		return;
	    }
	    foreach (string service_id, string service_name, known_services, {
		if (SuSEFirewall::IsServiceSupportedInZone(service_id, zone)) {
		    table_items = add (table_items, [ zone, service_id, service_name ]);
		    // detailed listing of used ports
		    if (detailed) {
			 map <string, list <string> > needed_ports = SuSEFirewallServices::GetNeededPortsAndProtocols(service_id);
			 foreach (string short_def, [ "tcp_ports", "udp_ports", "rpc_ports", "ip_protocols" ], {
			    if (size(needed_ports[short_def]:[])>0) {
				foreach (string port, needed_ports[short_def]:[], {
				    table_items = add (table_items, [
					"", sformat ("> %1: %2", detailed_def[short_def]:"", port)
				    ]);
				    table_items = add (table_items, [""]);
				});
			    }
			 });
		    }
		}
	    });
	});
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Zone"),
		// TRANSLATORS: CommandLine table header item
		_("Service ID"),
		// TRANSLATORS: CommandLine table header item
		_("Service Name")
	    ], table_items, $[]
	));

	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Additional Allowed Ports"),0));
	CommandLine::Print("");
	table_items = [];
	foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
	    if (!contains(for_zones, zone)) return;
	    
	    if (zone=="INT" && protect_from_INT==false) {
		table_items = add (table_items, [
		    zone,
		    // TRANSLATORS: CommandLine table item (all ports are allowed in this zone)
		    "*" + _("All Ports") + "*",
		    // TRANSLATORS: CommandLine table item (this zone is not protected at all)
		    "*" + _("Entire Zone Unprotected") + "*"
		]);
		return;
	    }

	    foreach (string protocol, [ "TCP", "UDP", "RPC" ], {
		foreach (string port, SuSEFirewall::GetAdditionalServices(protocol, zone), {
		    table_items = add (table_items, [ zone, protocol, port ]);
		});
	    });
	});
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Zone"),
		// TRANSLATORS: CommandLine table header item
		_("Protocol"),
		// TRANSLATORS: CommandLine table header item
		_("Port")
	    ], table_items, $[]
	));
	CommandLine::Print("");

	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Allowed Additional IP Protocols in Zones"),0));
	CommandLine::Print("");
	table_items = [];
	foreach (string zone, SuSEFirewall::GetKnownFirewallZones(), {
	    if (!contains(for_zones, zone)) return;

	    if (zone=="INT" && protect_from_INT==false) {
		table_items = add (table_items, [
		    zone,
		    // TRANSLATORS: CommandLine table item (all protocols are allowed in this zone)
		    "*" + _("All IP Protocols") + "*",
		    // TRANSLATORS: CommandLine table item (this zone is not protected at all)
		    "*" + _("Entire Zone Unprotected") + "*"
		]);
		return;
	    }
	    
	    foreach (string protocol, SuSEFirewall::GetAdditionalServices("IP", zone), {
		table_items = add (table_items, [ zone, protocol ]);
	    });
	});
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Zone"),
		// TRANSLATORS: CommandLine table header item
		_("IP Protocol")
	    ], table_items, $[]
	));
	CommandLine::Print("");
    }

    void FWCMDServicesDefinedServicesManagement(string action, string zone, list <string> services) {
	foreach (string service, services, {
	    if (!SuSEFirewallServices::IsKnownService(service)) {
		// TRANSLATORS: CommandLine error message, %1 is a service id
		CommandLine::Error((sformat(_("Unknown service '%1'."), service)));
		services = filter (string service_item, services, {
		    return service_item != service;
		});
	    }
	});

	if (action=="add") {
	    SuSEFirewall::SetServicesForZones(services, [zone], true);
	} else {
	    SuSEFirewall::SetServicesForZones(services, [zone], false);
	}
    }
    void FWCMDServicesAdditionalPortsManagement(string action, string zone, list <string> ports_or_protocols, string type) {
	map <string, string> types = $[
	    "tcpport"		: "TCP",
	    "udpport"		: "UDP",
	    "rpcport"		: "RPC",
	    "ipprotocol"	: "IP",
	];
	string protocol = types[type]:nil;

	if (protocol!=nil) {
	    list <string> current = SuSEFirewall::GetAdditionalServices (protocol, zone);
	    if (action=="add") {
		current = (list <string>) union (current, ports_or_protocols);
	    } else {
		current = filter (string check_item, current, {
		    return (!contains(ports_or_protocols, check_item));
		});
	    }
	    SuSEFirewall::SetAdditionalServices(protocol, zone, current);
	} else {
	    y2error("Software error %1", type);
	}
    }

    void FWCMDServicesProtect(string zone, string protect) {
	protect = tolower(protect);
	if (!contains(["yes","no"], protect)) {
	    // TRANSLATORS: CommandLine error message, %1 is an option value, %2 is an option name
	    CommandLine::Error(sformat(_("Value '%1' is not allowed for option '%2'."), protect, "protect"));
	    return nil;
	}
	// Only Protect from Internal is supported
	if (zone!="INT") {
	    // TRANSLATORS: CommandLine error message
	    CommandLine::Error(_("Protection can only be set for internal zones."));
	    return nil;
	}
	SuSEFirewall::SetProtectFromInternalZone(protect=="yes");
    }

    boolean FWCMDServices (map options) {
	// listing all known defined services
	if (options["list"]:nil!=nil) {
	    FWCMDServicesList();
	    return false;
	} else if (options["show"]:nil!=nil) {
	    list <string> known_zones = SuSEFirewall::GetKnownFirewallZones();
	    string for_zone = (string) options["zone"]:nil;
	    if (for_zone!=nil) {
		if (!CheckZone(for_zone, true)) {
		    return false;
		} else {
		    known_zones = [ for_zone ];
		}
	    }
	    FWCMDServicesShow(known_zones, (options["detailed"]:nil!=nil));
	    return false;
	} else if (options["add"]:nil!=nil && options["remove"]:nil!=nil) {
	    // TRANSLATORS: CommandLine error message
	    CommandLine::Error(_("Only one action command is allowed here."));
	} else if (options["add"]:nil!=nil || options["remove"]:nil!=nil) {
	    string zone = (string) options["zone"]:"";
	    if (!CheckZone(zone, false)) return false;

	    // add o remove
	    string action = "add";
	    if (options["remove"]:nil!=nil) action = "remove";

	    integer count_entries = 0;
	    foreach (string type, [ "service", "tcpport", "udpport", "rpcport", "ipprotocol" ], {
		list <string> items = CommaSeparatedList(options[type]:"");
		if (size(items)>0) {
		    count_entries = count_entries + 1;
		    if (type == "service") {
			FWCMDServicesDefinedServicesManagement(action, zone, items);
		    } else {
			FWCMDServicesAdditionalPortsManagement(action, zone, items, type);
		    }
		}
	    });

	    // checking if any action was set along with an action command
	    if (count_entries==0) {
		CommandLine::Error(sformat(
		    // TRANSLATORS: CommandLine error message, %1 is a list of possible entries (without translation)
		    _("At least one of '%1' must be set."),
		    "service, tcpport, udpport, rpcport, protocol"
		));
	    }
	    return true;
	} else if (options["protect"]:nil!=nil) {
	    string zone = (string) options["zone"]:"";
	    if (!CheckZone(zone, false)) return false;

	    FWCMDServicesProtect(zone, (string) options["protect"]:nil);
	} else {
	    CommandLine::Error(sformat(
		    // TRANSLATORS: CommandLine error message, %1 is a list of possible action commands
		    _("At least one action command from '%1' must be set."),
		    "list, show, add, remove"
	    ));
	}
    }

    void FWCMDMasqRedirectShow (map options) {
	CommandLine::Print("");
	// TRANSLATORS: CommandLine header
	CommandLine::Print(String::UnderlinedHeader(_("Redirect Requests to Masqueraded IP"),0));
	CommandLine::Print("");
	
	list <list <string> > table_items = [];
	list <map <string, string> > records = SuSEFirewall::GetListOfForwardsIntoMasquerade();
	integer counter = 0;
	foreach (map <string, string> record, records, {
	    counter = counter + 1;
	    // if redirect_to_port is not defined, use the same as requested_port
	    if (record["to_port"]:""=="" || record["to_port"]:""==nil) record["to_port"] = record["req_port"]:"";
	    // using port names instead of port numbers
	    if (options["names"]:nil!=nil) {
		foreach (string key, [ "to_port", "req_port" ], {
		    string port_name = GetPortName(record[key]:"");
		    if (port_name!=nil) {
			record[key] = port_name;
		    }
		});
	    }
	    table_items = add (table_items, [
		tostring(counter),
		record["source_net"]:"", record["protocol"]:"", record["req_ip"]:"", record["req_port"]:"",
		record["forward_to"]:"", record["to_port"]:"",
	    ]);
	});
	CommandLine::Print(String::TextTable(
	    [
		// TRANSLATORS: CommandLine table header item
		_("Id"),
		// TRANSLATORS: CommandLine table header item
		_("Source Network"),
		// TRANSLATORS: CommandLine table header item
		_("Protocol"),
		// TRANSLATORS: CommandLine table header item
		_("Req. IP"),
		// TRANSLATORS: CommandLine table header item
		_("Req. Port"),
		// TRANSLATORS: CommandLine table header item
		_("Redir. to IP"),
		// TRANSLATORS: CommandLine table header item
		_("Redir. to Port")
		],
	    table_items, $[]
	));
	CommandLine::Print("");
    }

    boolean FWCMDMasqRedirect (map options) {
	if (options["show"]:nil!=nil) {
	    FWCMDMasqRedirectShow(options);
	    return false;
	} else if (options["add"]:nil!=nil) {
	    // checking existency
	    boolean checked = true;
	    foreach (string option, [ "sourcenet", "protocol", "req_port", "redir_ip" ], {
		if (options[option]:nil==nil) {
		    // TRANSLATORS: CommandLine error, %1 is needed parameter name
		    CommandLine::Error(sformat(_("Parameter '%1' must be set"), option));
		    checked = false;
		}
	    });
	    if (!checked) return false;

	    // filling strings
	    map <string, string> new = $[];
	    foreach (string option, [ "sourcenet", "protocol", "req_port", "redir_ip", "req_ip", "redir_port" ], {
		new[option] = (string) options[option]:"";
	    });

	    // checking format
	    new["protocol"] = tolower(new["protocol"]:"");
	    if (!contains(["tcp","udp"], new["protocol"]:"")) {
		// TRANSLATORS: CommandLine error message, %1 is an option value, %2 is an option name
		CommandLine::Error(sformat(_("Value '%1' is not allowed for option '%2'."), new["protocol"]:"", "protocol"));
		return false;
	    }
	    
	    // checking port names (if known)
	    string port_errors = "";
	    foreach (string key, [ "req_port", "redir_port" ], {
		if (new[key]:nil!=nil) {
		    string port_number = GetPortNumber(new[key]:"");
		    if (port_number!=nil) {
			// internally using port numbers instead port names
			new[key] = port_number;
		    } else {
			port_errors = port_errors + (port_errors!="" ? "\n":"") +
			    // TRANSLATORS: CommandLine error message, %1 is a port name
			    sformat(_("Unknown port name '%1'."), new[key]:"");
		    }
		}
	    });
	    // there were some errors in port names
	    if (port_errors!="") {
		CommandLine::Error(port_errors);
		return false;
	    }
	    
	    SuSEFirewall::AddForwardIntoMasqueradeRule(
		new["sourcenet"]:"",  new["redir_ip"]:"", new["protocol"]:"", new["req_port"]:"",
		new["redir_port"]:"", new["req_ip"]:""
	    );
	    return true;
	} else if (options["remove"]:nil!=nil) {
	    if (options["record"]:nil==nil) {
		// TRANSLATORS: CommandLine error, %1 is needed parameter name
		CommandLine::Error(sformat(_("Parameter '%1' must be set"), "record"));
		return false;
	    }
	    integer record = (integer) options["record"]:0;
	    // records are printed 1-n but internally are 0-(n-1)
	    record = record - 1;
	    SuSEFirewall::RemoveForwardIntoMasqueradeRule(record);
	    return true;
	}
    }

    boolean FWCMDMasquerade (map options) {
	if (options["show"]:nil!=nil) {
	    CommandLine::Print("");
	    // TRANSLATORS: CommandLine header
	    CommandLine::Print(String::UnderlinedHeader(_("Masquerading Settings"),0));
	    CommandLine::Print("");
	    CommandLine::Print(sformat(
		// TRANSLATORS: CommandLine informative text, %1 is "enabled" or "disabled"
		_("Masquerading is %1"),
		(SuSEFirewall::GetMasquerade()==true ?
		    // TRANSLATORS: CommandLine masquerade status
		    _("enabled")
		    :
		    // TRANSLATORS: CommandLine masquerade status
		    _("disabled"))
	    ));
	    CommandLine::Print("");
	    return false;
	} else if (options["enable"]:nil!=nil) {
	    SuSEFirewall::SetMasquerade(true);
	} else if (options["disable"]:nil!=nil) {
	    SuSEFirewall::SetMasquerade(false);
	}
    }

    map cmdline = $[
	"id" : "firewall",
	// TRANSLATORS: CommandLine help heder
	"help" : _("Firewall Configuration"),
	"initialize" : SuSEFirewall::Read,
	"finish" : SuSEFirewall::Write,
	"actions" : $[
	    "startup" : $[
		"handler" : FWCMDStartup,
		// TRANSLATORS: CommandLine help
		"help" : _("Start-up settings"),
		"example" : [
		    "startup show",
		    "startup atboot",
		    "startup manual",
		],
	    ],
	    "zones" : $[
		"handler" : FWCMDZones,
		// TRANSLATORS: CommandLine help
		"help" : _("Known firewall zones"),
		"example" : "zones list",
	    ],
	    "interfaces" : $[
		"handler" : FWCMDInterfaces,
		// TRANSLATORS: CommandLine help
		"help" : _("Network interfaces configuration"),
		"example" : [
		    "interfaces show",
		    "interfaces add interface=eth0 zone=INT",
		],
	    ],
	    "services" : $[
		"handler" : FWCMDServices,
		// TRANSLATORS: CommandLine help
		"help" : _("Allowed services, ports, and protocols"),
		"example" : [
		    "services show detailed",
		    "services set protect=yes zone=INT",
		    "services add service=dhcp-server zone=EXT",
		    "services remove ipprotocol=esp tcpport=12,13,ipp zone=DMZ",
		],
	    ],
	    "broadcast" : $[
		"handler" : FWCMDBroadcast,
		// TRANSLATORS: CommandLine help
		"help" : _("Broadcast packets settings"),
		"example" : "broadcast add zone=INT port=ipp,233",
	    ],
	    "masquerade" : $[
		"handler" : FWCMDMasquerade,
		// TRANSLATORS: CommandLine 
		"help" : _("Masquerading settings"),
		"example" : [
		    "masquerade show",
		    "masquerade enable",
		],
	    ],
	    "masqredirect" : $[
		"handler" : FWCMDMasqRedirect,
		// TRANSLATORS: CommandLine help
		"help" : _("Redirect Requests to Masqueraded IP"),
		"example" : "masqredirect remove record=6",
	    ],
	    "logging" : $[
		"handler" : FWCMDLogging,
		// TRANSLATORS: CommandLine help
		"help" : _("Logging settings"),
		"example" : [
		    "logging set accepted=critical",
		    "logging set logbroadcast=no zone=INT",
		],
	    ],
	    "summary" : $[
		"handler" : FWCMDSummary,
		// TRANSLATORS: CommandLine help
		"help" : _("Firewall configuration summary"),
		"example" : [
		    "summary",
		    "summary zone=EXT",
		],
	    ],
	],
	"options" : $[
	    "show" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Show current settings"),
	    ],
	    "atboot" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Start firewall in the boot process"),
	    ],
	    "manual" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Start firewall manually"),
	    ],
	    "list" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("List configured entries"),
	    ],
	    "zone" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Zone short name"),
	    ],
	    "add" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Add a new record"),
	    ],
	    "remove" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Remove a record"),
	    ],
	    "interface" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Network interface configuration name"),
	    ],
	    "accepted" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Logging accepted packets (all|crit|none)"),
	    ],
	    "nonaccepted" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Logging not accepted packets (all|crit|none)"),
	    ],
	    "logbroadcast" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Logging broadcast packets (yes|no)"),
	    ],
	    "set" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Set value"),
	    ],
	    "port" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Port name or number; comma-separate multiple ports"),
	    ],
	    "service" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Known firewall service; comma-separate multiple services"),
	    ],
	    "tcpport" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("TCP port name or number; comma-separate multiple ports"),
	    ],
	    "udpport" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("UDP port name or number; comma-separate multiple ports"),
	    ],
	    "rpcport" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("RPC port name; comma-separate multiple ports"),
	    ],
	    "ipprotocol" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("IP protocol name; comma-separate multiple protocols"),
	    ],
	    "protect" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Set zone protection (yes|no)"),
	    ],
	    "detailed" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Detailed information"),
	    ],
	    "enable" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Enable option"),
	    ],
	    "disable" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Disable option"),
	    ],
	    "sourcenet" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Source network, such as 0/0 or 145.12.35.0/255.255.255.0"),
	    ],
	    "protocol" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Protocol (tcp|udp)"),
	    ],
	    "req_ip" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Requested external IP (optional)"),
	    ],
	    "req_port" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Requested port name or number"),
	    ],
	    "redir_ip" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Redirect to internal IP"),
	    ],
	    "redir_port" : $[
		"type" : "string",
		// TRANSLATORS: CommandLine help
		"help" : _("Redirect to port on internal IP (optional)"),
	    ],
	    "record" : $[
		"type" : "integer",
		// TRANSLATORS: CommandLine help
		"help" : _("Record number"),
	    ],
	    "names" : $[
		// TRANSLATORS: CommandLine help
		"help" : _("Use port names instead of port numbers"),
	    ],
	],
	"mappings" : $[
	    "startup" : [
		"show", "atboot", "manual",
	    ],
	    "zones" : [
		"list",
	    ],
	    "interfaces" : [
		"show", "add", "remove",
		"interface", "zone",
	    ],
	    "services" : [
		"list", "show", "add", "remove", "set",
		"detailed", "zone", "service", "tcpport", "udpport", "rpcport", "ipprotocol", "protect",
	    ],
	    "masquerade" : [
		"show",
		"enable", "disable",
	    ],
	    "masqredirect" : [
		"show", "add", "remove",
		"sourcenet", "protocol", "req_ip", "req_port", "redir_ip", "redir_port", "record", "names",
	    ],
	    "logging" : [
		"show", "set",
		"accepted", "nonaccepted", "logbroadcast", "zone",
	    ],
	    "broadcast" : [
		"show", "add", "remove",
		"zone", "port",
	    ],
	    "summary" : [
		"zone"
	    ],
	],
    ];

    y2milestone("----------------------------------------");
    y2milestone(sformat("Starting CommandLine with parameters %1", WFM::Args()));
    SummaryInitCommandLine();
    CommandLine::Run(cmdline);
    y2milestone("----------------------------------------");

/* EOF */
}
