Compare commits
108 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
996b80701e | ||
|
|
56a1588f96 | ||
|
|
aa7d243558 | ||
|
|
dcb6b5e117 | ||
|
|
067bbaf136 | ||
|
|
02724e7427 | ||
|
|
9f7cd8358f | ||
|
|
a06eab4ae1 | ||
|
|
0f54cfef92 | ||
|
|
fa69bf1da3 | ||
|
|
e7e1e67fc7 | ||
|
|
fae6f15fbe | ||
|
|
ebdd4d59b4 | ||
|
|
6f8ab2d9ec | ||
|
|
4363971e05 | ||
|
|
2cddcb14f6 | ||
|
|
ed89f965bf | ||
|
|
07750a74ba | ||
|
|
5955087887 | ||
|
|
61d054216d | ||
|
|
780f556e9c | ||
|
|
3f1e411f95 | ||
|
|
7e5fd9e655 | ||
|
|
8f4062f4da | ||
|
|
2624a47e88 | ||
|
|
56461e0173 | ||
|
|
4bbf33e119 | ||
|
|
e928445c91 | ||
|
|
94f9604493 | ||
|
|
a221be1818 | ||
|
|
b9b523d293 | ||
|
|
0003dd9c8c | ||
|
|
63c3e67c07 | ||
|
|
6df412401c | ||
|
|
284b13c137 | ||
|
|
c946e2d263 | ||
|
|
8608700ba9 | ||
|
|
6994edf40b | ||
|
|
f60a419e84 | ||
|
|
280869f883 | ||
|
|
9c58dcd145 | ||
|
|
a9c944483b | ||
|
|
61caf1c5eb | ||
|
|
0c2b510130 | ||
|
|
01b41130e5 | ||
|
|
fb763397b4 | ||
|
|
a7ed289c04 | ||
|
|
927b3dfe54 | ||
|
|
0000eed295 | ||
|
|
49df562431 | ||
|
|
d544247a53 | ||
|
|
04cb6cc6ff | ||
|
|
4d35e1845b | ||
|
|
c463d1d203 | ||
|
|
1aac7c1a4c | ||
|
|
8031d30ad2 | ||
|
|
ad771dfe3b | ||
|
|
00cd284e54 | ||
|
|
a925c32ecb | ||
|
|
be1fc5ce77 | ||
|
|
6accd9056f | ||
|
|
1cd908092b | ||
|
|
9d9f3b7afb | ||
|
|
8ca6049b32 | ||
|
|
fcdc42ea40 | ||
|
|
56c5212374 | ||
|
|
13bb8928c9 | ||
|
|
0bece3c17a | ||
|
|
9924b85773 | ||
|
|
8b50f8d07c | ||
|
|
9a53289a23 | ||
|
|
6e71870648 | ||
|
|
d7544e6192 | ||
|
|
d9a8ed29e8 | ||
|
|
9f86b661cb | ||
|
|
33cc594e39 | ||
|
|
35f1987b14 | ||
|
|
ff7a427189 | ||
|
|
7b90358c1e | ||
|
|
ef347b3a28 | ||
|
|
0c908cf913 | ||
|
|
1688d250dc | ||
|
|
8f4b665fb3 | ||
|
|
addfe66863 | ||
|
|
9353496864 | ||
|
|
936c1a4fa0 | ||
|
|
8e4e24a9b9 | ||
|
|
31f89d1813 | ||
|
|
dbb9b7014f | ||
|
|
e48a29a3f1 | ||
|
|
1f16691715 | ||
|
|
baf1d4a604 | ||
|
|
968fd0ca40 | ||
|
|
852567122e | ||
|
|
eefbd2ef87 | ||
|
|
11d2901fc7 | ||
|
|
0864b3a5ba | ||
|
|
05ac4be397 | ||
|
|
f8ca312cfa | ||
|
|
292ed31c4d | ||
|
|
5de4e5e9e9 | ||
|
|
fc0c2fe6da | ||
|
|
45f0a5d543 | ||
|
|
e97d70d152 | ||
|
|
d0bd3cc033 | ||
|
|
803c6baaea | ||
|
|
2f621b80d5 | ||
|
|
7773f82726 |
78
README.md
@@ -1,29 +1,75 @@
|
||||
# IPFire 2.x - The Open Source Firewall
|
||||
# BPFire - eBPF Network Firewall and Load Balancer
|
||||
|
||||
# What is IPFire?
|
||||
# What is BPFire?
|
||||
|
||||
IPFire is a hardened, versatile, state-of-the-art Open Source firewall based on
|
||||
Linux. Its ease of use, high performance in any scenario and extensibility make
|
||||
it usable for everyone. For a full list of features have a look [here](https://www.ipfire.org/features).
|
||||
BPFire is fork of IPFire 2.x, a hardened, versatile, state-of-the-art Open Source firewall based on Linux. BPFire is an eBPF networking centric Linux OS distribution that is easy for users to install and use. Current supported eBPF network application features:
|
||||
|
||||
This repository contains the source code of IPFire 2.x which is used to build
|
||||
the whole distribution from scratch, since IPFire is not based on any other
|
||||
distribution.
|
||||
1. XDP DDoS protection, See XDP SYNPROXY stops 10G DDoS SYN flood [here](https://www.youtube.com/watch?v=81Hgoy-x1A4)
|
||||
2. eBPF based LoxiLB load balancer, overall load balancer features located [here](https://loxilb-io.github.io/loxilbdocs/#overall-features-of-loxilb)
|
||||
|
||||
# Where can I get IPFire?
|
||||
# Where can I get BPFire installation image?
|
||||
|
||||
Just head over to https://www.ipfire.org/download
|
||||
https://drive.google.com/drive/folders/1HPJTWP6wi5gPd5gyiiKvIhWipqguptzZ?usp=drive_link
|
||||
|
||||
# How do I use this software?
|
||||
|
||||
We have a long and detailed wiki located [here](https://wiki.ipfire.org/) which
|
||||
should answers most of your questions.
|
||||
BPFire XDP DDoS feature demo:
|
||||
|
||||
[](https://www.youtube.com/watch?v=1pdNgoP-Kho "Enable IPFire eBPF XDP DDoS from WebUI")
|
||||
|
||||
IPFire have a long and detailed wiki located [here](https://wiki.ipfire.org/) which
|
||||
should answers most of your questions for IPFire.
|
||||
|
||||
# BPFire SYNPROXY throughput with and without XDP acceleration under 10Gbit DDoS SYN flood:
|
||||
|
||||
[](https://www.youtube.com/watch?v=81Hgoy-x1A4 "Throughput performance")
|
||||
|
||||
|
||||
# BPFire WebUI screenshot:
|
||||
|
||||
English:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Chinese:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# Does BPFire run in hypervisor virtual environment?
|
||||
|
||||
Yes, We have tested in Linux KVM hypervisor, Proxmox, Microsoft Hyper-v, should support Virtualbox, VMware as well.
|
||||
|
||||
Microsoft Hyper-v screen shot:
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
# But I have some questions left. Where can I get support?
|
||||
|
||||
You can ask your question at our community located [here](https://community.ipfire.org/).
|
||||
A complete list of our support channels can be found [here](https://www.ipfire.org/support).
|
||||
You can ask your question by open github issue report or discussion or
|
||||
You can ask your question at ipfire community located [here](https://community.ipfire.org/) that is IPFire related.
|
||||
|
||||
# How can I contribute?
|
||||
# How to build BPFire?
|
||||
|
||||
We have another document for this. Please look [here](doc/CONTRIBUTING.md).
|
||||
Build Environment Setup https://www.ipfire.org/docs/devel/ipfire-2-x/build-initial
|
||||
|
||||
git clone https://github.com/vincentmli/BPFire.git
|
||||
|
||||
cd BPFire
|
||||
|
||||
git checkout bpfire
|
||||
|
||||
get BPFire source tar balls https://drive.google.com/file/d/1YjTzik4xw0JxFDldLZdVw1GthXG5QrS_/view?usp=drive_link
|
||||
|
||||
tar xvf cache.tar
|
||||
|
||||
./make.sh build
|
||||
|
||||
9
config/cfgroot/ddos-settings
Normal file
@@ -0,0 +1,9 @@
|
||||
22=off
|
||||
ENABLE_DDOS=off
|
||||
25=off
|
||||
80=off
|
||||
53=off
|
||||
8080=off
|
||||
8090=off
|
||||
443=off
|
||||
5555=off
|
||||
1
config/cfgroot/dns-ddos-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_DNS_DDOS=off
|
||||
@@ -366,6 +366,14 @@ sub validip
|
||||
}
|
||||
}
|
||||
|
||||
sub validnum {
|
||||
my $num = shift;
|
||||
if ($num =~ /^\d+$/) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub validmask {
|
||||
my $mask = shift;
|
||||
|
||||
@@ -1306,6 +1314,22 @@ sub grab_address_from_file($) {
|
||||
return;
|
||||
}
|
||||
|
||||
sub get_ipaddresses_from_interface($) {
|
||||
my ($interface) = @_;
|
||||
my @ip_addresses;
|
||||
|
||||
my $output = `ip addr show $interface 2>/dev/null`;
|
||||
|
||||
# Check if the command was successful
|
||||
if ($? == 0) {
|
||||
# Extract IP addresses using regex
|
||||
while ($output =~ /inet (\d+\.\d+\.\d+\.\d+)/g) {
|
||||
push @ip_addresses, $1;
|
||||
}
|
||||
}
|
||||
return @ip_addresses;
|
||||
}
|
||||
|
||||
# Function to get all configured and enabled nameservers.
|
||||
sub get_nameservers () {
|
||||
my %settings;
|
||||
|
||||
1
config/cfgroot/loxilb-FWconfig.txt
Normal file
@@ -0,0 +1 @@
|
||||
{"fwAttr":[{"opts":{"counter":"0:0","doSnat":true,"toIP":"REDIP"},"ruleArguments":{"destinationIP":"0.0.0.0/0","portName":"green0","sourceIP":"0.0.0.0/0"}}]}
|
||||
1
config/cfgroot/loxilb-settings
Normal file
@@ -0,0 +1 @@
|
||||
ENABLE_LOXILB=off
|
||||
8
config/cfgroot/tcp_ports
Normal file
@@ -0,0 +1,8 @@
|
||||
ssh 22/tcp # The Secure Shell (SSH) Protocol
|
||||
smtp 25/tcp # Simple Mail Transfer
|
||||
http 80/tcp # World Wide Web HTTP
|
||||
https 443/tcp # http protocol over TLS/SSL
|
||||
domain 53/tcp # Domain Name Server
|
||||
httpalt 8080/tcp # HTTP Alternate (see port 80)
|
||||
opsmessaging 8090/tcp # Vehicle to station messaging
|
||||
userdefined 5555/tcp # Vehicle to station messaging
|
||||
5
config/cfgroot/udp-ddos-settings
Normal file
@@ -0,0 +1,5 @@
|
||||
53=off
|
||||
ENABLE_UDP_DDOS=off
|
||||
5060=off
|
||||
5061=off
|
||||
10408=off
|
||||
5
config/cfgroot/udp_ports
Normal file
@@ -0,0 +1,5 @@
|
||||
domain 53/udp # Domain Name Server
|
||||
game1 10408/udp # Domain Name Server
|
||||
sip 5060/udp # Voice over Internet
|
||||
siptls 5061/udp # Voice over Internet TLS
|
||||
|
||||
@@ -42,6 +42,8 @@ my $CHAIN = $CHAIN_FORWARD;
|
||||
my $CHAIN_NAT_SOURCE = "NAT_SOURCE";
|
||||
my $CHAIN_NAT_DESTINATION = "NAT_DESTINATION";
|
||||
my $CHAIN_MANGLE_NAT_DESTINATION_FIX = "NAT_DESTINATION";
|
||||
my $CHAIN_INSYNPROXY = "INSYNPROXY";
|
||||
my $CHAIN_RAWSYNPROXY = "RAWSYNPROXY";
|
||||
my @VALID_CHAINS = ($CHAIN_INPUT, $CHAIN_FORWARD, $CHAIN_OUTPUT);
|
||||
my @ANY_ADDRESSES = ("0.0.0.0/0.0.0.0", "0.0.0.0/0", "0/0");
|
||||
|
||||
@@ -218,6 +220,8 @@ sub flush {
|
||||
run("$IPTABLES -F $CHAIN_INPUT");
|
||||
run("$IPTABLES -F $CHAIN_FORWARD");
|
||||
run("$IPTABLES -F $CHAIN_OUTPUT");
|
||||
run("$IPTABLES -F $CHAIN_INSYNPROXY");
|
||||
run("$IPTABLES -t raw -F $CHAIN_RAWSYNPROXY");
|
||||
run("$IPTABLES -t nat -F $CHAIN_NAT_SOURCE");
|
||||
run("$IPTABLES -t nat -F $CHAIN_NAT_DESTINATION");
|
||||
run("$IPTABLES -t mangle -F $CHAIN_MANGLE_NAT_DESTINATION_FIX");
|
||||
@@ -297,6 +301,12 @@ sub buildrules {
|
||||
$NAT_MODE = uc($$hash{$key}[31]);
|
||||
}
|
||||
|
||||
# Check if XDP SYNPROXY is turned on
|
||||
my $SYNPROXY;
|
||||
if(exists($$hash{$key}[37])) {
|
||||
$SYNPROXY = ($$hash{$key}[37] eq 'ON');
|
||||
}
|
||||
|
||||
# Set up time constraints.
|
||||
my @time_options = ();
|
||||
if ($$hash{$key}[18] eq 'ON') {
|
||||
@@ -608,6 +618,23 @@ sub buildrules {
|
||||
}
|
||||
run("$IPTABLES -A $chain @options @source_intf_options @destination_intf_options -j $target");
|
||||
|
||||
if ($SYNPROXY) {
|
||||
my $dport = &get_external_port($hash, $key);
|
||||
my @raw_options = ("-p", "tcp", "-m", "tcp", "--syn");
|
||||
my @in_options = ("-p", "tcp", "-m", "tcp");
|
||||
my @options = ("--sack-perm", "--timestamp", "--wscale", "7", "--mss", "1460");
|
||||
push(@raw_options, "--dport", "$dport");
|
||||
push(@in_options, "--dport", "$dport", "-m", "state", "--state", "INVALID,UNTRACKED");
|
||||
if ($LOG) {
|
||||
run("$IPTABLES -t raw -A $CHAIN_RAWSYNPROXY -i $RED_DEV @raw_options -j LOG --log-prefix '$CHAIN_RAWSYNPROXY '");
|
||||
}
|
||||
run("$IPTABLES -t raw -A $CHAIN_RAWSYNPROXY -i $RED_DEV @raw_options -j CT --notrack");
|
||||
if ($LOG) {
|
||||
run("$IPTABLES -A $CHAIN_INSYNPROXY -i $RED_DEV @in_options -j LOG --log-prefix '$CHAIN_RAWSYNPROXY ' @options");
|
||||
}
|
||||
run("$IPTABLES -A $CHAIN_INSYNPROXY -i $RED_DEV @in_options -j SYNPROXY @options");
|
||||
}
|
||||
|
||||
# Handle forwarding rules and add corresponding rules for firewall access.
|
||||
if ($chain eq $CHAIN_FORWARD) {
|
||||
# If the firewall is part of the destination subnet and access to the destination network
|
||||
@@ -945,6 +972,22 @@ sub get_dnat_target_port {
|
||||
}
|
||||
}
|
||||
|
||||
sub get_external_port {
|
||||
my $hash = shift;
|
||||
my $key = shift;
|
||||
|
||||
if ($$hash{$key}[14] eq "TGT_PORT") {
|
||||
my $port = $$hash{$key}[15];
|
||||
my $external_port = $$hash{$key}[30];
|
||||
|
||||
if ($external_port && ($port ne $external_port)) {
|
||||
return $external_port;
|
||||
} else {
|
||||
return $port;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub add_dnat_mangle_rules {
|
||||
my $nat_address = shift;
|
||||
my $interface = shift;
|
||||
|
||||
8
config/kernel/kernel.config.bpf
Normal file
@@ -0,0 +1,8 @@
|
||||
CONFIG_BPF_SYSCALL=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_INFO_BTF=y
|
||||
CONFIG_DEBUG_INFO_DWARF4=y
|
||||
CONFIG_BPF_UNPRIV_DEFAULT_OFF=y
|
||||
CONFIG_KPROBES=y
|
||||
CONFIG_KPROBE_EVENTS=y
|
||||
CONFIG_BPF_EVENTS=y
|
||||
@@ -386,10 +386,10 @@ CONFIG_DMI=y
|
||||
# CONFIG_GART_IOMMU is not set
|
||||
CONFIG_BOOT_VESA_SUPPORT=y
|
||||
# CONFIG_MAXSMP is not set
|
||||
CONFIG_NR_CPUS_RANGE_BEGIN=2
|
||||
CONFIG_NR_CPUS_RANGE_BEGIN=512
|
||||
CONFIG_NR_CPUS_RANGE_END=512
|
||||
CONFIG_NR_CPUS_DEFAULT=64
|
||||
CONFIG_NR_CPUS=64
|
||||
CONFIG_NR_CPUS_DEFAULT=512
|
||||
CONFIG_NR_CPUS=512
|
||||
CONFIG_SCHED_CLUSTER=y
|
||||
CONFIG_SCHED_SMT=y
|
||||
CONFIG_SCHED_MC=y
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
'enabled' => 1,
|
||||
'subMenu' => $subproxy
|
||||
};
|
||||
$menu->{'07.ipfire'} = {'caption' => 'IPFire',
|
||||
$menu->{'07.ipfire'} = {'caption' => 'BPFire',
|
||||
'enabled' => 1,
|
||||
'subMenu' => $subipfire
|
||||
};
|
||||
|
||||
@@ -1,8 +1,32 @@
|
||||
$subipfire->{'10.pakfire'} = {'caption' => 'Pakfire',
|
||||
'uri' => '/cgi-bin/pakfire.cgi',
|
||||
'title' => "Pakfire",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'10.ddos'} = {'caption' => $Lang::tr{'ebpf xdp ddos'},
|
||||
'uri' => '/cgi-bin/ddos.cgi',
|
||||
'title' => "$Lang::tr{'ebpf xdp ddos system'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'20.loxilb'} = {
|
||||
'caption' => $Lang::tr{'loxilb enable'},
|
||||
'uri' => '/cgi-bin/loxilb.cgi',
|
||||
'title' => "$Lang::tr{'loxilb enable'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'30.loxilbconfig'} = {
|
||||
'caption' => $Lang::tr{'loxilb config'},
|
||||
'uri' => '/cgi-bin/loxilbconfig.cgi',
|
||||
'title' => "$Lang::tr{'loxilb config'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'40.loxilbfw'} = {
|
||||
'caption' => $Lang::tr{'loxilb fw'},
|
||||
'uri' => '/cgi-bin/loxilbfw.cgi',
|
||||
'title' => "$Lang::tr{'loxilb fw'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'50.keepalived'} = {
|
||||
'caption' => $Lang::tr{'keepalived'},
|
||||
'uri' => '/cgi-bin/keepalived.cgi',
|
||||
'title' => "$Lang::tr{'keepalived'}",
|
||||
'enabled' => 1,
|
||||
};
|
||||
$subipfire->{'99.help'} = {'caption' => $Lang::tr{'help'},
|
||||
'uri' => '/cgi-bin/help.cgi',
|
||||
'title' => "$Lang::tr{'help'}",
|
||||
|
||||
@@ -92,6 +92,7 @@ etc/rc.d/init.d/unbound
|
||||
etc/rc.d/init.d/vnstat
|
||||
etc/rc.d/init.d/waitdrives
|
||||
etc/rc.d/init.d/wlanclient
|
||||
etc/rc.d/init.d/ddos
|
||||
#etc/rc.d/rc0.d
|
||||
#etc/rc.d/rc0.d/K01imspetor
|
||||
#etc/rc.d/rc0.d/K01motion
|
||||
|
||||
2
config/rootfiles/common/bpftool
Normal file
@@ -0,0 +1,2 @@
|
||||
usr/sbin/bpftool
|
||||
usr/share/bash-completion/completions/bpftool
|
||||
@@ -98,6 +98,7 @@ var/ipfire/langs
|
||||
#var/ipfire/langs/pl.pl
|
||||
#var/ipfire/langs/ru.pl
|
||||
#var/ipfire/langs/tr.pl
|
||||
#var/ipfire/langs/zh.pl
|
||||
var/ipfire/logging
|
||||
#var/ipfire/logging/settings
|
||||
var/ipfire/mac
|
||||
@@ -199,3 +200,5 @@ var/ipfire/wakeonlan
|
||||
var/ipfire/wireless
|
||||
#var/ipfire/wireless/config
|
||||
#var/ipfire/wireless/settings
|
||||
var/ipfire/ddos
|
||||
var/ipfire/loxilb
|
||||
|
||||
@@ -38,3 +38,5 @@ usr/sbin/keepalived
|
||||
#usr/share/man/man5/keepalived.conf.5
|
||||
#usr/share/man/man8/keepalived.8
|
||||
var/ipfire/backup/addons/includes/keepalived
|
||||
var/ipfire/keepalived
|
||||
etc/rc.d/rc3.d/S101keepalived
|
||||
3
config/rootfiles/common/libbpf
Normal file
@@ -0,0 +1,3 @@
|
||||
usr/include/bpf/xsk.h
|
||||
usr/lib/libbpf.so.0
|
||||
usr/lib/libbpf.so.0.8.3
|
||||
9
config/rootfiles/common/libbsd
Normal file
@@ -0,0 +1,9 @@
|
||||
usr/lib/libbsd-ctor.a
|
||||
usr/lib/libbsd.a
|
||||
usr/lib/libbsd.la
|
||||
usr/lib/libbsd.so
|
||||
usr/lib/libbsd.so.0
|
||||
usr/lib/libbsd.so.0.12.2
|
||||
usr/lib/pkgconfig/libbsd-ctor.pc
|
||||
usr/lib/pkgconfig/libbsd-overlay.pc
|
||||
usr/lib/pkgconfig/libbsd.pc
|
||||
6
config/rootfiles/common/libmd
Normal file
@@ -0,0 +1,6 @@
|
||||
usr/lib/libmd.a
|
||||
usr/lib/libmd.la
|
||||
usr/lib/libmd.so
|
||||
usr/lib/libmd.so.0
|
||||
usr/lib/libmd.so.0.1.0
|
||||
usr/lib/pkgconfig/libmd.pc
|
||||
1
config/rootfiles/common/loxicmd
Normal file
@@ -0,0 +1 @@
|
||||
usr/bin/loxicmd
|
||||
7
config/rootfiles/common/loxilb
Normal file
@@ -0,0 +1,7 @@
|
||||
opt/loxilb/llb_ebpf_emain.o
|
||||
opt/loxilb/llb_ebpf_main.o
|
||||
opt/loxilb/llb_kern_sock.o
|
||||
opt/loxilb/llb_xdp_main.o
|
||||
opt/loxilb/loxilb_libdp.o
|
||||
usr/bin/loxilb
|
||||
etc/rc.d/rc3.d/S100loxilb
|
||||
1
config/rootfiles/common/loxilb-tc
Normal file
@@ -0,0 +1 @@
|
||||
usr/bin/ntc
|
||||
@@ -38,3 +38,6 @@ usr/local/bin/urlfilterctrl
|
||||
usr/local/bin/wirelessclient
|
||||
usr/local/bin/wirelessctrl
|
||||
#usr/local/bin/wlanapctrl
|
||||
usr/local/bin/ddosctrl
|
||||
usr/local/bin/loxilbctrl
|
||||
usr/local/bin/keepalivedctrl
|
||||
|
||||
@@ -23,6 +23,7 @@ usr/lib/openssh/sftp-server
|
||||
usr/lib/openssh/ssh-pkcs11-helper
|
||||
usr/lib/openssh/ssh-sk-helper
|
||||
usr/sbin/sshd
|
||||
usr/lib/openssh/sshd-session
|
||||
#usr/share/man/man1/scp.1
|
||||
#usr/share/man/man1/sftp.1
|
||||
#usr/share/man/man1/ssh-add.1
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
etc/vimrc
|
||||
root/.vimrc
|
||||
usr/bin/ex
|
||||
usr/bin/rview
|
||||
usr/bin/rvim
|
||||
|
||||
@@ -90,6 +90,11 @@ srv/web/ipfire/cgi-bin/wireless.cgi
|
||||
srv/web/ipfire/cgi-bin/wirelessclient.cgi
|
||||
srv/web/ipfire/cgi-bin/wlanap.cgi
|
||||
srv/web/ipfire/cgi-bin/zoneconf.cgi
|
||||
srv/web/ipfire/cgi-bin/ddos.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilb.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilbconfig.cgi
|
||||
srv/web/ipfire/cgi-bin/loxilbfw.cgi
|
||||
srv/web/ipfire/cgi-bin/keepalived.cgi
|
||||
#srv/web/ipfire/html
|
||||
srv/web/ipfire/html/blob.gif
|
||||
#srv/web/ipfire/html/captive
|
||||
|
||||
@@ -91,6 +91,8 @@ etc/rc.d/init.d/unbound
|
||||
etc/rc.d/init.d/vnstat
|
||||
etc/rc.d/init.d/waitdrives
|
||||
etc/rc.d/init.d/wlanclient
|
||||
etc/rc.d/init.d/ddos
|
||||
etc/rc.d/init.d/loxilb
|
||||
#etc/rc.d/rc0.d
|
||||
#etc/rc.d/rc0.d/K01imspetor
|
||||
#etc/rc.d/rc0.d/K01motion
|
||||
|
||||
@@ -23699,3 +23699,4 @@ lib/modules/KVER-ipfire/modules.symbols
|
||||
lib/modules/KVER-ipfire/modules.symbols.bin
|
||||
#lib/modules/KVER-ipfire/source
|
||||
sbin/gen_init_cpio
|
||||
usr/sbin/bpftool
|
||||
|
||||
34
config/rootfiles/common/xdp-tools
Normal file
@@ -0,0 +1,34 @@
|
||||
usr/lib/bpf/xdp-dispatcher.o
|
||||
usr/lib/bpf/xdp_synproxy.bpf.o
|
||||
usr/lib/bpf/xdp_dnsrrl.bpf.o
|
||||
usr/lib/bpf/xdp_udp.bpf.o
|
||||
usr/sbin/xdp-udp
|
||||
usr/lib/bpf/xdpdump_bpf.o
|
||||
usr/lib/bpf/xdpdump_xdp.o
|
||||
usr/lib/bpf/xdpfilt_alw_all.o
|
||||
usr/lib/bpf/xdpfilt_alw_eth.o
|
||||
usr/lib/bpf/xdpfilt_alw_ip.o
|
||||
usr/lib/bpf/xdpfilt_alw_tcp.o
|
||||
usr/lib/bpf/xdpfilt_alw_udp.o
|
||||
usr/lib/bpf/xdpfilt_dny_all.o
|
||||
usr/lib/bpf/xdpfilt_dny_eth.o
|
||||
usr/lib/bpf/xdpfilt_dny_ip.o
|
||||
usr/lib/bpf/xdpfilt_dny_tcp.o
|
||||
usr/lib/bpf/xdpfilt_dny_udp.o
|
||||
usr/lib/bpf/xsk_def_xdp_prog.o
|
||||
usr/lib/bpf/xsk_def_xdp_prog_5.3.o
|
||||
usr/lib/libxdp.a
|
||||
usr/lib/libxdp.so
|
||||
usr/lib/libxdp.so.1
|
||||
usr/lib/libxdp.so.1.4.0
|
||||
usr/lib/pkgconfig/libxdp.pc
|
||||
usr/sbin/xdp-bench
|
||||
usr/sbin/xdp-filter
|
||||
usr/sbin/xdp-loader
|
||||
usr/sbin/xdp-monitor
|
||||
usr/sbin/xdp-trafficgen
|
||||
usr/sbin/xdp_synproxy
|
||||
usr/sbin/xdp-udp
|
||||
usr/sbin/xdpdump
|
||||
usr/share/xdp-tools/xdp_drop.o
|
||||
usr/share/xdp-tools/xdp_pass.o
|
||||
1
config/vim/.vimrc
Normal file
@@ -0,0 +1 @@
|
||||
set mouse-=a
|
||||
546
html/cgi-bin/ddos.cgi
Executable file
@@ -0,0 +1,546 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %ddossettings=();
|
||||
my %udpddossettings=();
|
||||
my %dnsddossettings=();
|
||||
my %checked=();
|
||||
my $errormessage='';
|
||||
my $counter = 0;
|
||||
my %tcp_ports=();
|
||||
my %udp_ports=();
|
||||
my $tcp_portfile = "${General::swroot}/ddos/tcp_ports";
|
||||
my $udp_portfile = "${General::swroot}/ddos/udp_ports";
|
||||
my $ddossettingfile = "${General::swroot}/ddos/settings";
|
||||
my $udpddossettingfile = "${General::swroot}/ddos/udp-ddos-settings";
|
||||
my $dnsddossettingfile = "${General::swroot}/ddos/dns-ddos-settings";
|
||||
|
||||
&get_tcp_ports();
|
||||
&get_udp_ports();
|
||||
|
||||
# Read configuration file.
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
$ddossettings{'ENABLE_DDOS'} = 'off';
|
||||
$udpddossettings{'ENABLE_UDP_DDOS'} = 'off';
|
||||
$dnsddossettings{'ENABLE_DNS_DDOS'} = 'off';
|
||||
$ddossettings{'ACTION'} = '';
|
||||
$udpddossettings{'UDP_ACTION'} = '';
|
||||
$udpddossettings{'DNS_ACTION'} = '';
|
||||
|
||||
&Header::getcgihash(\%ddossettings);
|
||||
|
||||
if ($ddossettings{'ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
# Loop through our locations array to prevent from
|
||||
# non existing countries or code.
|
||||
foreach my $p (values %tcp_ports) {
|
||||
# Check if blocking for this country should be enabled/disabled.
|
||||
if (exists $ddossettings{$p}) {
|
||||
$ddossettings{$p} = "on";
|
||||
} else {
|
||||
$ddossettings{$p} = "off";
|
||||
}
|
||||
}
|
||||
|
||||
&General::writehash("$ddossettingfile", \%ddossettings);
|
||||
|
||||
if ($ddossettings{'ENABLE_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%udpddossettings);
|
||||
|
||||
if ($udpddossettings{'UDP_ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
# Loop through our locations array to prevent from
|
||||
# non existing countries or code.
|
||||
foreach my $p (values %udp_ports) {
|
||||
# Check if blocking for this country should be enabled/disabled.
|
||||
if (exists $udpddossettings{$p}) {
|
||||
$udpddossettings{$p} = "on";
|
||||
} else {
|
||||
$udpddossettings{$p} = "off";
|
||||
}
|
||||
}
|
||||
|
||||
&General::writehash("$udpddossettingfile", \%udpddossettings);
|
||||
|
||||
if ($udpddossettings{'ENABLE_UDP_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%dnsddossettings);
|
||||
|
||||
if ($udpddossettings{'DNS_ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
&General::writehash("$dnsddossettingfile", \%dnsddossettings);
|
||||
|
||||
if ($dnsddossettings{'ENABLE_DNS_DDOS'} eq 'on') {
|
||||
&General::log($Lang::tr{'ddos is enabled'});
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/ddos/enableddos");
|
||||
&General::system('/usr/local/bin/ddosctrl', 'start');
|
||||
} else {
|
||||
&General::log($Lang::tr{'ddos is disabled'});
|
||||
&General::system('/usr/local/bin/ddosctrl', 'stop');
|
||||
unlink "${General::swroot}/ddos/enableddos";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'ebpf xdp ddos'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$ddossettingfile", \%ddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($ddossettings{'ENABLE_DDOS'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp tcp'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_DDOS' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp tcp port'});
|
||||
print <<END;
|
||||
|
||||
<table width='95%' class='tbl' id="countries">
|
||||
<tr>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
<td width='5%' bgcolor='$color{'color20'}'> </td>
|
||||
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
END
|
||||
|
||||
my $lines;
|
||||
my $lines2;
|
||||
my $col;
|
||||
|
||||
|
||||
# Sort output based on hash value port number
|
||||
for my $service ( sort { $tcp_ports{$a} cmp $tcp_ports{$b} }
|
||||
keys %tcp_ports )
|
||||
{
|
||||
my $port = $tcp_ports{$service};
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($ddossettings{$port} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Colour lines.
|
||||
if ($lines % 2) {
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
|
||||
# Grouping elements.
|
||||
my $line_start;
|
||||
my $line_end;
|
||||
if ($lines2 % 2) {
|
||||
# Increase lines (background color by once.
|
||||
$lines++;
|
||||
|
||||
# Add empty column in front.
|
||||
$line_start="<td $col> </td>";
|
||||
|
||||
# When the line number can be diveded by "2",
|
||||
# we are going to close the line.
|
||||
$line_end="</tr>";
|
||||
} else {
|
||||
# When the line number is not divideable by "2",
|
||||
# we are starting a new line.
|
||||
$line_start="<tr>";
|
||||
$line_end;
|
||||
}
|
||||
|
||||
print "$line_start<td align='center' $col><input type='checkbox' name='$port' $checked></td>\n";
|
||||
print "<td align='center' $col>$port</td>\n";
|
||||
print "<td align='left' $col>$service</td>$line_end\n";
|
||||
|
||||
$lines2++;
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
#
|
||||
# Read configuration file.
|
||||
&General::readhash("$dnsddossettingfile", \%dnsddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $dns_checked;
|
||||
if ($dnsddossettings{'ENABLE_DNS_DDOS'} eq "on") {
|
||||
$dns_checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp dns'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_DNS_DDOS' $dns_checked></td>
|
||||
<td align='center'><input type='submit' name='DNS_ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp dns ratelimit'}
|
||||
<td><input type='text' name='DNS_RATELIMIT' value='$dnsddossettings{'DNS_RATELIMIT'}'</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$udpddossettingfile", \%udpddossettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $udp_checked;
|
||||
if ($udpddossettings{'ENABLE_UDP_DDOS'} eq "on") {
|
||||
$udp_checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Print box to enable/disable locationblock.
|
||||
print"<form method='POST' action='$ENV{'SCRIPT_NAME'}'>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp udp'});
|
||||
print <<END;
|
||||
<table width='95%'>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp enable'}
|
||||
<td><input type='checkbox' name='ENABLE_UDP_DDOS' $udp_checked></td>
|
||||
<td align='center'><input type='submit' name='UDP_ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='base'>$Lang::tr{'xdp udp ratelimit'}
|
||||
<td><input type='text' name='UDP_RATELIMIT' value='$udpddossettings{'UDP_RATELIMIT'}'</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp udp port'});
|
||||
print <<END;
|
||||
|
||||
<table width='95%' class='tbl' id="countries">
|
||||
<tr>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
<td width='5%' bgcolor='$color{'color20'}'> </td>
|
||||
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'></td>
|
||||
<td width='5%' align='center' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'port'}</b>
|
||||
</td>
|
||||
<td with='35%' align='left' bgcolor='$color{'color20'}'>
|
||||
<b>$Lang::tr{'service'}</b>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
END
|
||||
|
||||
my $udp_lines;
|
||||
my $udp_lines2;
|
||||
my $udp_col;
|
||||
|
||||
# Sort output based on hash value port number
|
||||
for my $service ( sort { $udp_ports{$a} cmp $udp_ports{$b} }
|
||||
keys %udp_ports )
|
||||
{
|
||||
my $port = $udp_ports{$service};
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($udpddossettings{$port} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
# Colour lines.
|
||||
if ($udp_lines % 2) {
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
|
||||
# Grouping elements.
|
||||
my $line_start;
|
||||
my $line_end;
|
||||
if ($udp_lines2 % 2) {
|
||||
# Increase lines (background color by once.
|
||||
$lines++;
|
||||
|
||||
# Add empty column in front.
|
||||
$line_start="<td $udp_col> </td>";
|
||||
|
||||
# When the line number can be diveded by "2",
|
||||
# we are going to close the line.
|
||||
$line_end="</tr>";
|
||||
} else {
|
||||
# When the line number is not divideable by "2",
|
||||
# we are starting a new line.
|
||||
$line_start="<tr>";
|
||||
$line_end;
|
||||
}
|
||||
|
||||
print "$line_start<td align='center' $udp_col><input type='checkbox' name='$port' $checked></td>\n";
|
||||
print "<td align='center' $udp_col>$port</td>\n";
|
||||
print "<td align='left' $udp_col>$service</td>$line_end\n";
|
||||
|
||||
$udp_lines2++;
|
||||
}
|
||||
print <<END;
|
||||
</table>
|
||||
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
print "</form>\n";
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'xdp status'});
|
||||
|
||||
print <<END;
|
||||
<table class="tbl" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp interface'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp prio'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp program'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp mode'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp id'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp tag'}</strong>
|
||||
</th>
|
||||
<th align="center">
|
||||
<strong>$Lang::tr{'xdp action'}</strong>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
END
|
||||
|
||||
&printxdp();
|
||||
|
||||
print "</tbody>\n</table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
sub get_tcp_ports()
|
||||
{
|
||||
my $fh;
|
||||
open($fh, '<', $tcp_portfile) or die "Unable to open file: $!";
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
next if $line =~ /^\s*#/; # Skip comments
|
||||
my ($service, $port) = $line =~ /^(\w+)\s+(\d+)\/tcp/;
|
||||
if ($service && $port) {
|
||||
$tcp_ports{$service} = $port;
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub get_udp_ports()
|
||||
{
|
||||
my $fh;
|
||||
open($fh, '<', $udp_portfile) or die "Unable to open file: $!";
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
next if $line =~ /^\s*#/; # Skip comments
|
||||
my ($service, $port) = $line =~ /^(\w+)\s+(\d+)\/udp/;
|
||||
if ($service && $port) {
|
||||
$udp_ports{$service} = $port;
|
||||
}
|
||||
}
|
||||
close($fh);
|
||||
}
|
||||
|
||||
sub printxdp()
|
||||
{
|
||||
# print active SSH logins (grep outpout of "who -s")
|
||||
my @output = &General::system_output("/usr/local/bin/ddosctrl", "status");
|
||||
chomp(@output);
|
||||
|
||||
# list active logins...
|
||||
foreach my $line (@output)
|
||||
{
|
||||
my $interface;
|
||||
my $prio;
|
||||
my $prog;
|
||||
my $mode;
|
||||
my $id;
|
||||
my $tag;
|
||||
my $action;
|
||||
#comment next below when having issue
|
||||
#next if $line !~ /^red0/;
|
||||
#next if $line !~ /^\s=>/;
|
||||
next if $line =~ /No XDP program loaded!/;
|
||||
if ($line =~ /^red0/) {
|
||||
my @arry = split(/\s+/, $line);
|
||||
$interface = $arry[0];
|
||||
$prio = "N/A";
|
||||
$prog = $arry[1];
|
||||
$mode = $arry[2];
|
||||
$id = $arry[3];
|
||||
$tag = $arry[4];
|
||||
$action = "N/A";
|
||||
} elsif ($line =~ /^\s=>/) {
|
||||
my @arry = split(/\s+/, $line);
|
||||
$interface = "red0";
|
||||
$prio = $arry[2];
|
||||
$prog = $arry[3];
|
||||
$mode = "N/A";
|
||||
$id = $arry[4];
|
||||
$tag = $arry[5];
|
||||
$action = $arry[6];
|
||||
}
|
||||
if ($line =~ /^red0/ or $line =~ /^\s=>/) {
|
||||
my $table_colour = ($id % 2) ? $color{'color20'} : $color{'color22'};
|
||||
|
||||
print <<END;
|
||||
<tr bgcolor='$table_colour'>
|
||||
<td>$interface</td>
|
||||
<td>$prio</td>
|
||||
<td>$prog</td>
|
||||
<td>$mode</td>
|
||||
<td>$id</td>
|
||||
<td>$tag</td>
|
||||
<td>$action</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -42,11 +42,19 @@ our $filename1 = "${General::swroot}/dhcp/advoptions"; # Field separator is TAB
|
||||
# because we need commas in the some data
|
||||
our $filename2 = "${General::swroot}/dhcp/fixleases";
|
||||
our $filename3 = "${General::swroot}/dhcp/advoptions-list"; # Describe the allowed syntax for dhcp options
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
my $errormessage = '';
|
||||
my $warnNTPmessage = '';
|
||||
my @nosaved=();
|
||||
my %color = ();
|
||||
|
||||
our @IPFILE = ();
|
||||
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@IPFILE = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
#Basic syntax allowed for new Option definition. Not implemented: RECORDS & array of RECORDS
|
||||
our $OptionTypes = 'boolean|((un)?signed )?integer (8|16|32)|ip-address|text|string|encapsulate \w+|array of ip-address';
|
||||
|
||||
@@ -58,6 +66,7 @@ if (&Header::blue_used()){push(@ITFs,'BLUE');}
|
||||
foreach my $itf (@ITFs) {
|
||||
$dhcpsettings{"ENABLE_${itf}"} = 'off';
|
||||
$dhcpsettings{"ENABLEBOOTP_${itf}"} = 'off';
|
||||
$dhcpsettings{"ROUTER_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"START_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"END_ADDR_${itf}"} = '';
|
||||
$dhcpsettings{"DOMAIN_NAME_${itf}"} = '';
|
||||
@@ -144,6 +153,12 @@ if ($dhcpsettings{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($dhcpsettings{"ENABLE_${itf}"} eq 'on' ) {
|
||||
# "Start" is defined, need "End" and vice versa
|
||||
if ($dhcpsettings{"ROUTER_ADDR_${itf}"}) {
|
||||
if (!(&General::validip($dhcpsettings{"ROUTER_ADDR_${itf}"}))) {
|
||||
$errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid router address'};
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
if ($dhcpsettings{"START_ADDR_${itf}"}) {
|
||||
if (!(&General::validip($dhcpsettings{"START_ADDR_${itf}"}))) {
|
||||
$errormessage = "DHCP on ${itf}: " . $Lang::tr{'invalid start address'};
|
||||
@@ -571,14 +586,45 @@ foreach my $itf (@ITFs) {
|
||||
|
||||
if ($netsettings{"${itf}_DEV"} ne '' ) { # Show only defined interface
|
||||
my $lc_itf=lc($itf);
|
||||
print <<END
|
||||
my @gwips;
|
||||
my $current_gwip = $dhcpsettings{"ROUTER_ADDR_${itf}"};
|
||||
foreach my $line (@IPFILE) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq $netsettings{"${itf}_DEV"}) {
|
||||
my @tmp = split(/\//, $temp[0]);
|
||||
push(@gwips, $tmp[0]);
|
||||
}
|
||||
}
|
||||
push(@gwips, $netsettings{"${itf}_ADDRESS"}); #add primary ip of $itf/green0 as one of option ip
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='25%' class='boldbase'><b><font color='${lc_itf}'>$Lang::tr{"$lc_itf interface"}</font></b></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}
|
||||
<input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{'on'} /></td>
|
||||
<td width='25%' class='base'>$Lang::tr{'ip address'}<br />$Lang::tr{'netmask'}:</td><td><b>$netsettings{"${itf}_ADDRESS"}<br />$netsettings{"${itf}_NETMASK"}</b></td>
|
||||
</tr><tr>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'router address'} </td>
|
||||
<td>
|
||||
<select name='ROUTER_ADDR_${itf}' id='router_addr' style="width: 200px;">
|
||||
END
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $gwip (@gwips) {
|
||||
my $selected = '';
|
||||
if ($gwip eq $current_gwip ) {
|
||||
$selected = 'selected';
|
||||
}
|
||||
print "<option value=\"$gwip\" $selected>$gwip</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'start address'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='START_ADDR_${itf}' value='$dhcpsettings{"START_ADDR_${itf}"}' /></td>
|
||||
<td width='25%' class='base'>$Lang::tr{'end address'} <img src='/blob.gif' alt='*' /></td>
|
||||
@@ -620,10 +666,9 @@ print <<END
|
||||
</table>
|
||||
<hr />
|
||||
END
|
||||
;
|
||||
}# Show only defined interface
|
||||
}#foreach itf
|
||||
print <<END
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
@@ -632,7 +677,7 @@ print <<END
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
# DHCP DNS update support (RFC2136)
|
||||
@@ -1321,7 +1366,12 @@ sub buildconf {
|
||||
}
|
||||
print FILE "\toption subnet-mask " . $netsettings{"${itf}_NETMASK"} . ";\n";
|
||||
print FILE "\toption domain-name \"" . $dhcpsettings{"DOMAIN_NAME_${itf}"} . "\";\n";
|
||||
print FILE "\toption routers " . $netsettings{"${itf}_ADDRESS"} . ";\n";
|
||||
if ($dhcpsettings{"ROUTER_ADDR_${itf}"}) {
|
||||
my @temp = split("\/", $dhcpsettings{"ROUTER_ADDR_${itf}"});
|
||||
print FILE "\toption routers " . $temp[0] . ";\n";
|
||||
} else {
|
||||
print FILE "\toption routers " . $netsettings{"${itf}_ADDRESS"} . ";\n";
|
||||
}
|
||||
print FILE "\toption domain-name-servers " . $dhcpsettings{"DNS1_${itf}"} if ($dhcpsettings{"DNS1_${itf}"});
|
||||
print FILE ", " . $dhcpsettings{"DNS2_${itf}"} if ($dhcpsettings{"DNS2_${itf}"});
|
||||
print FILE ";\n" if ($dhcpsettings{"DNS1_${itf}"});
|
||||
|
||||
@@ -92,6 +92,7 @@ my $configovpn = "${General::swroot}/ovpn/settings";
|
||||
my $fwoptions = "${General::swroot}/optionsfw/settings";
|
||||
my $ifacesettings = "${General::swroot}/ethernet/settings";
|
||||
my $errormessage='';
|
||||
my $maxkey;
|
||||
my $hint='';
|
||||
my $ipgrp="${General::swroot}/outgoing/groups";
|
||||
my $tdcolor='';
|
||||
@@ -129,9 +130,15 @@ print<<END;
|
||||
|
||||
// Check if we are dealing with a protocol, that knows ports.
|
||||
if (\$.inArray(protocol, PROTOCOLS_WITH_PORTS) >= 0) {
|
||||
if (protocol === "TCP") {
|
||||
\$("#XDP_SYNPROXY").show();
|
||||
} else {
|
||||
\$("#XDP_SYNPROXY").hide();
|
||||
}
|
||||
\$("#PROTOCOL_PORTS").show();
|
||||
} else {
|
||||
\$("#PROTOCOL_PORTS").hide();
|
||||
\$("#XDP_SYNPROXY").hide();
|
||||
}
|
||||
|
||||
// Handle ICMP.
|
||||
@@ -214,7 +221,6 @@ if ($fwdfwsettings{'ACTION'} eq 'saverule')
|
||||
&General::readhasharray("$configinput", \%configinputfw);
|
||||
&General::readhasharray("$configoutgoing", \%configoutgoingfw);
|
||||
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
|
||||
my $maxkey;
|
||||
#Set Variables according to the JQuery code in protocol section
|
||||
if ($fwdfwsettings{'PROT'} eq 'TCP' || $fwdfwsettings{'PROT'} eq 'UDP')
|
||||
{
|
||||
@@ -298,57 +304,12 @@ if ($fwdfwsettings{'ACTION'} eq 'saverule')
|
||||
$maxkey=&General::findhasharraykey(\%configfwdfw);
|
||||
%rulehash=%configfwdfw;
|
||||
}
|
||||
#check if we have an identical rule already
|
||||
if($fwdfwsettings{'oldrulenumber'} eq $fwdfwsettings{'rulepos'}){
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'ruleremark'},$fwdfwsettings{'LOG'},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[16],$rulehash{$key}[17],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
|
||||
}
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage='';
|
||||
}
|
||||
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
|
||||
$fwdfwsettings{'nosave'} = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#check Rulepos on new Rule
|
||||
if($fwdfwsettings{'rulepos'} > 0 && !$fwdfwsettings{'oldrulenumber'}){
|
||||
$fwdfwsettings{'oldrulenumber'}=$maxkey;
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
}
|
||||
}
|
||||
}
|
||||
#check if we just close a rule
|
||||
if( $fwdfwsettings{'oldgrp1a'} eq $fwdfwsettings{'grp1'} && $fwdfwsettings{'oldgrp1b'} eq $fwdfwsettings{$fwdfwsettings{'grp1'}} && $fwdfwsettings{'oldgrp2a'} eq $fwdfwsettings{'grp2'} && $fwdfwsettings{'oldgrp2b'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'oldgrp3a'} eq $fwdfwsettings{'grp3'} && $fwdfwsettings{'oldgrp3b'} eq $fwdfwsettings{$fwdfwsettings{'grp3'}} && $fwdfwsettings{'oldusesrv'} eq $fwdfwsettings{'USESRV'} && $fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'oldruletype'} eq $fwdfwsettings{'chain'}){
|
||||
if($fwdfwsettings{'nosave'} eq 'on' && $fwdfwsettings{'updatefwrule'} eq 'on'){
|
||||
$fwdfwsettings{'nosave2'} = 'on';
|
||||
$errormessage='';
|
||||
}
|
||||
}
|
||||
#check max concurrent connections per ip address
|
||||
if ($fwdfwsettings{'LIMIT_CON_CON'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'concon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err concon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'concon'}='';
|
||||
}
|
||||
#check ratelimit value
|
||||
if ($fwdfwsettings{'RATE_LIMIT'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'ratecon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err ratecon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'ratecon'}='';
|
||||
}
|
||||
|
||||
&checkrulepos;
|
||||
&checkruleclose;
|
||||
&checkruleconlimit;
|
||||
&checkruleratelimit;
|
||||
|
||||
#increase counters
|
||||
if (!$errormessage){
|
||||
if ($fwdfwsettings{'nosave2'} ne 'on'){
|
||||
@@ -959,6 +920,74 @@ sub checkrule
|
||||
$fwdfwsettings{'ICMP_TYPES'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkrulepos
|
||||
{
|
||||
#check if we have an identical rule already
|
||||
if($fwdfwsettings{'oldrulenumber'} eq $fwdfwsettings{'rulepos'}){
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'ruleremark'},$fwdfwsettings{'LOG'},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'},$fwdfwsettings{'USE_SYNPROXY'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[16],$rulehash{$key}[17],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36],$rulehash{$key}[37]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage=$Lang::tr{'fwdfw err remark'}."<br>";
|
||||
}
|
||||
if($fwdfwsettings{'oldruleremark'} ne $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'updatefwrule'} eq 'on' && $fwdfwsettings{'ruleremark'} ne '' && &validremark($fwdfwsettings{'ruleremark'})){
|
||||
$errormessage='';
|
||||
}
|
||||
if ($fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'}){
|
||||
$fwdfwsettings{'nosave'} = 'on';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#check Rulepos on new Rule
|
||||
if($fwdfwsettings{'rulepos'} > 0 && !$fwdfwsettings{'oldrulenumber'}){
|
||||
$fwdfwsettings{'oldrulenumber'}=$maxkey;
|
||||
foreach my $key (sort keys %rulehash){
|
||||
if ( "$fwdfwsettings{'RULE_ACTION'},$fwdfwsettings{'ACTIVE'},$fwdfwsettings{'grp1'},$fwdfwsettings{$fwdfwsettings{'grp1'}},$fwdfwsettings{'grp2'},$fwdfwsettings{$fwdfwsettings{'grp2'}},$fwdfwsettings{'USE_SRC_PORT'},$fwdfwsettings{'PROT'},$fwdfwsettings{'ICMP_TYPES'},$fwdfwsettings{'SRC_PORT'},$fwdfwsettings{'USESRV'},$fwdfwsettings{'TGT_PROT'},$fwdfwsettings{'ICMP_TGT'},$fwdfwsettings{'grp3'},$fwdfwsettings{$fwdfwsettings{'grp3'}},$fwdfwsettings{'TIME'},$fwdfwsettings{'TIME_MON'},$fwdfwsettings{'TIME_TUE'},$fwdfwsettings{'TIME_WED'},$fwdfwsettings{'TIME_THU'},$fwdfwsettings{'TIME_FRI'},$fwdfwsettings{'TIME_SAT'},$fwdfwsettings{'TIME_SUN'},$fwdfwsettings{'TIME_FROM'},$fwdfwsettings{'TIME_TO'},$fwdfwsettings{'USE_NAT'},$fwdfwsettings{$fwdfwsettings{'nat'}},$fwdfwsettings{'dnatport'},$fwdfwsettings{'nat'},$fwdfwsettings{'LIMIT_CON_CON'},$fwdfwsettings{'concon'},$fwdfwsettings{'RATE_LIMIT'},$fwdfwsettings{'ratecon'},$fwdfwsettings{'RATETIME'},$fwdfwsettings{'USE_SYNPROXY'}"
|
||||
eq "$rulehash{$key}[0],$rulehash{$key}[2],$rulehash{$key}[3],$rulehash{$key}[4],$rulehash{$key}[5],$rulehash{$key}[6],$rulehash{$key}[7],$rulehash{$key}[8],$rulehash{$key}[9],$rulehash{$key}[10],$rulehash{$key}[11],$rulehash{$key}[12],$rulehash{$key}[13],$rulehash{$key}[14],$rulehash{$key}[15],$rulehash{$key}[18],$rulehash{$key}[19],$rulehash{$key}[20],$rulehash{$key}[21],$rulehash{$key}[22],$rulehash{$key}[23],$rulehash{$key}[24],$rulehash{$key}[25],$rulehash{$key}[26],$rulehash{$key}[27],$rulehash{$key}[28],$rulehash{$key}[29],$rulehash{$key}[30],$rulehash{$key}[31],$rulehash{$key}[32],$rulehash{$key}[33],$rulehash{$key}[34],$rulehash{$key}[35],$rulehash{$key}[36],$rulehash{$key}[37]"){
|
||||
$errormessage.=$Lang::tr{'fwdfw err ruleexists'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleclose
|
||||
{
|
||||
#check if we just close a rule
|
||||
if( $fwdfwsettings{'oldgrp1a'} eq $fwdfwsettings{'grp1'} && $fwdfwsettings{'oldgrp1b'} eq $fwdfwsettings{$fwdfwsettings{'grp1'}} && $fwdfwsettings{'oldgrp2a'} eq $fwdfwsettings{'grp2'} && $fwdfwsettings{'oldgrp2b'} eq $fwdfwsettings{$fwdfwsettings{'grp2'}} && $fwdfwsettings{'oldgrp3a'} eq $fwdfwsettings{'grp3'} && $fwdfwsettings{'oldgrp3b'} eq $fwdfwsettings{$fwdfwsettings{'grp3'}} && $fwdfwsettings{'oldusesrv'} eq $fwdfwsettings{'USESRV'} && $fwdfwsettings{'oldruleremark'} eq $fwdfwsettings{'ruleremark'} && $fwdfwsettings{'oldruletype'} eq $fwdfwsettings{'chain'}){
|
||||
if($fwdfwsettings{'nosave'} eq 'on' && $fwdfwsettings{'updatefwrule'} eq 'on'){
|
||||
$fwdfwsettings{'nosave2'} = 'on';
|
||||
$errormessage='';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleconlimit
|
||||
{
|
||||
#check max concurrent connections per ip address
|
||||
if ($fwdfwsettings{'LIMIT_CON_CON'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'concon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err concon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'concon'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkruleratelimit
|
||||
{
|
||||
#check ratelimit value
|
||||
if ($fwdfwsettings{'RATE_LIMIT'} eq 'ON'){
|
||||
if (!($fwdfwsettings{'ratecon'} =~ /^(\d+)$/)) {
|
||||
$errormessage.=$Lang::tr{'fwdfw err ratecon'};
|
||||
}
|
||||
}else{
|
||||
$fwdfwsettings{'ratecon'}='';
|
||||
}
|
||||
}
|
||||
|
||||
sub checkvpn
|
||||
{
|
||||
my $ip=shift;
|
||||
@@ -1624,6 +1653,7 @@ sub newrule
|
||||
$fwdfwsettings{'RATE_LIMIT'} = $hash{$key}[34];
|
||||
$fwdfwsettings{'ratecon'} = $hash{$key}[35];
|
||||
$fwdfwsettings{'RATETIME'} = $hash{$key}[36];
|
||||
$fwdfwsettings{'USE_SYNPROXY'} = $hash{$key}[37];
|
||||
$checked{'grp1'}{$fwdfwsettings{'grp1'}} = 'CHECKED';
|
||||
$checked{'grp2'}{$fwdfwsettings{'grp2'}} = 'CHECKED';
|
||||
$checked{'grp3'}{$fwdfwsettings{'grp3'}} = 'CHECKED';
|
||||
@@ -1640,6 +1670,7 @@ sub newrule
|
||||
$checked{'TIME_SAT'}{$fwdfwsettings{'TIME_SAT'}} = 'CHECKED';
|
||||
$checked{'TIME_SUN'}{$fwdfwsettings{'TIME_SUN'}} = 'CHECKED';
|
||||
$checked{'USE_NAT'}{$fwdfwsettings{'USE_NAT'}} = 'CHECKED';
|
||||
$checked{'USE_SYNPROXY'}{$fwdfwsettings{'USE_SYNPROXY'}} = 'CHECKED';
|
||||
$checked{'nat'}{$fwdfwsettings{'nat'}} = 'CHECKED';
|
||||
$checked{'LIMIT_CON_CON'}{$fwdfwsettings{'LIMIT_CON_CON'}} = 'CHECKED';
|
||||
$checked{'RATE_LIMIT'}{$fwdfwsettings{'RATE_LIMIT'}} = 'CHECKED';
|
||||
@@ -1661,6 +1692,7 @@ sub newrule
|
||||
$fwdfwsettings{'oldusesrv'}=$fwdfwsettings{'USESRV'};
|
||||
$fwdfwsettings{'oldruleremark'}=$fwdfwsettings{'ruleremark'};
|
||||
$fwdfwsettings{'oldnat'}=$fwdfwsettings{'USE_NAT'};
|
||||
$fwdfwsettings{'oldsynproxy'}=$fwdfwsettings{'USE_SYNPROXY'};
|
||||
$fwdfwsettings{'oldruletype'}=$fwdfwsettings{'chain'};
|
||||
$fwdfwsettings{'oldconcon'}=$fwdfwsettings{'LIMIT_CON_CON'};
|
||||
$fwdfwsettings{'olduseratelimit'}=$fwdfwsettings{'RATE_LIMIT'};
|
||||
@@ -1688,6 +1720,7 @@ sub newrule
|
||||
$fwdfwsettings{'oldusesrv'}=$fwdfwsettings{'USESRV'};
|
||||
$fwdfwsettings{'oldruleremark'}=$fwdfwsettings{'ruleremark'};
|
||||
$fwdfwsettings{'oldnat'}=$fwdfwsettings{'USE_NAT'};
|
||||
$fwdfwsettings{'oldsynproxy'}=$fwdfwsettings{'USE_SYNPROXY'};
|
||||
$fwdfwsettings{'oldconcon'}=$fwdfwsettings{'LIMIT_CON_CON'};
|
||||
#check if manual ip (source) is orange network
|
||||
if ($fwdfwsettings{'grp1'} eq 'src_addr'){
|
||||
@@ -1901,6 +1934,18 @@ END
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<table width="40%" border="0" id="XDP_SYNPROXY">
|
||||
<tr>
|
||||
<!-- #USE_SYNPROXY -->
|
||||
<td>
|
||||
$Lang::tr{'fwdfw use synproxy'}
|
||||
</td>
|
||||
|
||||
<td>
|
||||
<input type='checkbox' name='USE_SYNPROXY' id='USE_SYNPROXY' value="ON" $checked{'USE_SYNPROXY'}{'ON'}>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<table width="100%" border="0" id="PROTOCOL_PORTS">
|
||||
<tr>
|
||||
<!-- #SOURCEPORT -->
|
||||
@@ -2198,6 +2243,7 @@ END
|
||||
<input type='hidden' name='oldruleremark' value='$fwdfwsettings{'oldruleremark'}' />
|
||||
<input type='hidden' name='oldorange' value='$fwdfwsettings{'oldorange'}' />
|
||||
<input type='hidden' name='oldnat' value='$fwdfwsettings{'oldnat'}' />
|
||||
<input type='hidden' name='oldsynproxy' value='$fwdfwsettings{'oldsynproxy'}' />
|
||||
<input type='hidden' name='oldruletype' value='$fwdfwsettings{'oldruletype'}' />
|
||||
<input type='hidden' name='oldconcon' value='$fwdfwsettings{'oldconcon'}' />
|
||||
<input type='hidden' name='ACTION' value='saverule' ></form><form method='post' style='display:inline'><input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'><input type='hidden' name='ACTION' value'reset'></td></td>
|
||||
@@ -2341,6 +2387,7 @@ sub saverule
|
||||
$$hash{$key}[34] = $fwdfwsettings{'RATE_LIMIT'};
|
||||
$$hash{$key}[35] = $fwdfwsettings{'ratecon'};
|
||||
$$hash{$key}[36] = $fwdfwsettings{'RATETIME'};
|
||||
$$hash{$key}[37] = $fwdfwsettings{'USE_SYNPROXY'};
|
||||
&General::writehasharray("$config", $hash);
|
||||
}else{
|
||||
foreach my $key (sort {$a <=> $b} keys %$hash){
|
||||
@@ -2382,6 +2429,7 @@ sub saverule
|
||||
$$hash{$key}[34] = $fwdfwsettings{'RATE_LIMIT'};
|
||||
$$hash{$key}[35] = $fwdfwsettings{'ratecon'};
|
||||
$$hash{$key}[36] = $fwdfwsettings{'RATETIME'};
|
||||
$$hash{$key}[37] = $fwdfwsettings{'USE_SYNPROXY'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
376
html/cgi-bin/keepalived.cgi
Normal file
@@ -0,0 +1,376 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
use experimental 'smartmatch';
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
our %hasettings=();
|
||||
our %netsettings=();
|
||||
my %mainsettings=();
|
||||
my %timesettings=();
|
||||
my $setting = "${General::swroot}/keepalived/settings";
|
||||
my $runsetting = "${General::swroot}/keepalived/runsettings";
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
# because we need commas in the some data
|
||||
my $errormessage = '';
|
||||
#remove 'ENABLE_HA' from '/var/ipfire/keepalived/settings' as it could affect keepalived running state
|
||||
my @nosaved=('ENABLE_HA');
|
||||
my %color = ();
|
||||
|
||||
$hasettings{'ENABLE_HA'} = 'off';
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
&Header::showhttpheaders();
|
||||
our @ITFs=('RED', 'GREEN');
|
||||
my @STATE= ('MASTER', 'BACKUP');
|
||||
my $DUMMY_IP = '192.0.2.1'; #for HA master/backup state tracking
|
||||
|
||||
#Settings1 for the first screen box
|
||||
foreach my $itf (@ITFs) {
|
||||
$hasettings{"ENABLE_${itf}"} = 'off';
|
||||
$hasettings{"state_${itf}"} = '';
|
||||
$hasettings{"garp_master_delay_${itf}"} = '';
|
||||
$hasettings{"virtual_router_id_${itf}"} = '';
|
||||
$hasettings{"priority_${itf}"} = '';
|
||||
$hasettings{"advert_int_${itf}"} = '';
|
||||
$hasettings{"auth_pass_${itf}"} = '';
|
||||
$hasettings{"unicast_peer_${itf}"} = '';
|
||||
$hasettings{"virtual_ipaddress_${itf}"} = '';
|
||||
}
|
||||
|
||||
# Read Ipcop settings
|
||||
&General::readhash("${General::swroot}/ethernet/settings", \%netsettings);
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%hasettings);
|
||||
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'enable'})
|
||||
{
|
||||
#remove @nosaved from $hasettings before writehash to 'runsettings' file since 'runsetting' is only for keepalived running state
|
||||
foreach my $itf (@ITFs) {
|
||||
my @nosaved = ("virtual_router_id_${itf}", "priority_${itf}", "unicast_peer_${itf}", "auth_pass_${itf}", "garp_master_delay_${itf}", "advert_int_${itf}", "virtual_ipaddress_${itf}", "state_${itf}", "ENABLE_${itf}");
|
||||
map (delete ($hasettings{$_}) ,(@nosaved));
|
||||
}
|
||||
&General::writehash("$runsetting", \%hasettings);
|
||||
if ($hasettings{'ENABLE_HA'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/keepalived/enable_ha");
|
||||
&General::system('/usr/local/bin/keepalivedctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/keepalivedctrl', 'stop');
|
||||
unlink "${General::swroot}/keepalived/enable_ha";
|
||||
}
|
||||
}
|
||||
|
||||
# Check Settings1 first because they are needed by &buildconf
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'save'}) {
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($hasettings{"ENABLE_${itf}"} eq 'on' ) {
|
||||
|
||||
if (!(&General::validnum($hasettings{"virtual_router_id_${itf}"})) || ($hasettings{"virtual_router_id_${itf}"} eq '')) {
|
||||
$errormessage = "virtual_router_id" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"priority_${itf}"})) || ($hasettings{"priority_${itf}"} eq '')) {
|
||||
$errormessage = "priority" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"advert_int_${itf}"})) || ($hasettings{"advert_int_${itf}"} eq '')) {
|
||||
$errormessage = "advert_int" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
if (!(&General::validnum($hasettings{"garp_master_delay_${itf}"})) || ($hasettings{"garp_master_delay_${itf}"} eq '')) {
|
||||
$errormessage = "garp master delay" . " is $Lang::tr{'required field'}" . " or not valid num";
|
||||
goto ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
map (delete ($hasettings{$_}) ,@nosaved,'ACTION','KEY1','KEY2','q'); # Must not be saved
|
||||
&General::writehash($setting, \%hasettings); # Save good settings
|
||||
$hasettings{'ACTION'} = $Lang::tr{'save'}; # create an 'ACTION'
|
||||
map ($hasettings{$_} = '',@nosaved,'KEY1','KEY2'); # and reinit vars to empty
|
||||
&buildconf;
|
||||
ERROR:
|
||||
}
|
||||
|
||||
if ($hasettings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
|
||||
# Set default DHCP values only if blank and disabled
|
||||
foreach my $itf (@ITFs) {
|
||||
if ($hasettings{"ENABLE_${itf}"} ne 'on' ) {
|
||||
$hasettings{"virtual_router_id_${itf}"} = '50';
|
||||
$hasettings{"priority_${itf}"} = '100';
|
||||
$hasettings{"advert_int_${itf}"} = '1';
|
||||
$hasettings{"auth_pass_${itf}"} = '';
|
||||
$hasettings{"unicast_peer_${itf}"} = '';
|
||||
$hasettings{"garp_master_delay_${itf}"} = '10';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
### START PAGE ###
|
||||
&Header::openpage($Lang::tr{'keepalived configuration'}, 1, $Header::extraHead);
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$runsetting", \%hasettings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($hasettings{'ENABLE_HA'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $hastate = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'standby'}</font></b></td></tr></table>";
|
||||
|
||||
my @ips = &General::get_ipaddresses_from_interface("green0");
|
||||
|
||||
if (grep { $_ eq $DUMMY_IP } @ips) {
|
||||
$hastate = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'active'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/keepalivedctrl', 'status');
|
||||
|
||||
if (grep(/is running/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'keepalived status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'keepalived status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
<td align='center'>$hastate</td>
|
||||
<td align='right'>
|
||||
<form method='GET' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='submit' value='Refresh'>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='4'> </td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='100%' class='boldbase'>$Lang::tr{'enable'}
|
||||
<td align='left'><input type='checkbox' name='ENABLE_HA' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'enable'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
|
||||
&General::readhash($setting, \%hasettings); # Get saved settings and reset to good if needed
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'keepalived config'});
|
||||
print "<form method='post' action='$ENV{'SCRIPT_NAME'}'>";
|
||||
|
||||
foreach my $itf (@ITFs) {
|
||||
my %checked = ();
|
||||
my @vips;
|
||||
my $lc_itf = lc($itf);
|
||||
my $current_state = $hasettings{"state_${itf}"};
|
||||
my @current_vips = split(/\|/, $hasettings{"virtual_ipaddress_${itf}"}); #multi selected value is separated by pipe |
|
||||
|
||||
foreach my $line (@current) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq $netsettings{"${itf}_DEV"}) {
|
||||
push(@vips, $temp[0]);
|
||||
}
|
||||
}
|
||||
$checked{'ENABLE'}{'on'} = ($hasettings{"ENABLE_${itf}"} ne 'on') ? '' : "checked='checked'";
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='25%' class='boldbase'><b><font color='$lc_itf'>$Lang::tr{"$lc_itf interface"}</font></b></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}
|
||||
<input type='checkbox' name='ENABLE_${itf}' $checked{'ENABLE'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'keepalived state'}: </td>
|
||||
<td>
|
||||
<select name='state_${itf}' id='state' style="width: 95px;">
|
||||
END
|
||||
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $state (@STATE) {
|
||||
my $selected = ($state eq $current_state) ? 'selected' : '';
|
||||
print "<option value=\"$state\" $selected>$state</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived virtual router id'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='virtual_router_id_${itf}' value='$hasettings{"virtual_router_id_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived priority'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='priority_${itf}' value='$hasettings{"priority_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived advert int'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='advert_int_${itf}' value='$hasettings{"advert_int_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived garp master delay'} </td>
|
||||
<td width='25%'><input type='text' name='garp_master_delay_${itf}' value='$hasettings{"garp_master_delay_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived auth pass'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='auth_pass_${itf}' value='$hasettings{"auth_pass_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='25%' class='base'>$Lang::tr{'keepalived unicast peer'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td width='25%'><input type='text' name='unicast_peer_${itf}' value='$hasettings{"unicast_peer_${itf}"}' /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'keepalived virtual address'}: <img src='/blob.gif' alt='*' /></td>
|
||||
<td>
|
||||
<select name='virtual_ipaddress_${itf}' id='virtual_ipaddress' style="width: 200px;" multiple>
|
||||
END
|
||||
|
||||
# display selected, tip from chatgpt
|
||||
foreach my $vip (@vips) {
|
||||
my $selected = (grep { $_ eq $vip } @current_vips) ? 'selected' : '';
|
||||
print "<option value=\"$vip\" $selected>$vip</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<hr />
|
||||
END
|
||||
} # foreach itf
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='40%' align='right'><input type='submit' name='ACTION' value='$Lang::tr{'save'}' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
# Build the configuration file mixing settings, fixed leases and advanced options
|
||||
sub buildconf {
|
||||
open(FILE, ">/${General::swroot}/keepalived/keepalived.conf") or die "Unable to write keepalived.conf file";
|
||||
flock(FILE, 2);
|
||||
|
||||
# Global settings
|
||||
print FILE "global_defs {\n";
|
||||
print FILE "\trouter_id BPFire_DEVEL\n";
|
||||
print FILE "}\n";
|
||||
|
||||
print FILE "\n";
|
||||
|
||||
#Subnet range definition
|
||||
foreach my $itf (@ITFs) {
|
||||
my $lc_itf=lc($itf);
|
||||
if ($hasettings{"ENABLE_${itf}"} eq 'on' ){
|
||||
print FILE "vrrp_instance VI_$lc_itf {" . "\n";
|
||||
print FILE "\tstate " . $hasettings{"state_${itf}"} . "\n";
|
||||
print FILE "\tinterface " . $netsettings{"${itf}_DEV"} . "\n";
|
||||
print FILE "\tvirtual_router_id " . $hasettings{"virtual_router_id_${itf}"} . "\n";
|
||||
print FILE "\tpriority " . $hasettings{"priority_${itf}"} . "\n";
|
||||
print FILE "\tadvert_int " . $hasettings{"advert_int_${itf}"} . "\n";
|
||||
print FILE "\tgarp_master_delay " . $hasettings{"garp_master_delay_${itf}"} . "\n";
|
||||
#unicast peer, red0 does not support multicast
|
||||
print FILE "\tunicast_peer {" . "\n";
|
||||
print FILE "\t\t" . $hasettings{"unicast_peer_${itf}"} . "\n";
|
||||
print FILE "\t}" . "\n";
|
||||
# authentication
|
||||
print FILE "\tauthentication {" . "\n";
|
||||
print FILE "\t\tauth_type PASS" . "\n";
|
||||
print FILE "\t\tauth_pass " . $hasettings{"auth_pass_${itf}"} . "\n";
|
||||
print FILE "\t}" . "\n";
|
||||
# virtual ipaddress
|
||||
print FILE "\tvirtual_ipaddress {" . "\n";
|
||||
print FILE "\t\t$DUMMY_IP" . "\n";
|
||||
my @vips = split(/\|/, $hasettings{"virtual_ipaddress_${itf}"});
|
||||
foreach my $ip (@vips) {
|
||||
print FILE "\t\t$ip" . "\n";
|
||||
}
|
||||
print FILE "\t}" . "\n";
|
||||
|
||||
print FILE "} #$itf\n\n";
|
||||
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/keepalived/enable_${lc_itf}");
|
||||
} else {
|
||||
unlink "${General::swroot}/keepalived/enable_${lc_itf}";
|
||||
}
|
||||
}
|
||||
|
||||
close FILE;
|
||||
|
||||
&General::system_background('/usr/local/bin/keepalivedctrl', 'restart');
|
||||
}
|
||||
894
html/cgi-bin/keepalivedvs.cgi
Normal file
@@ -0,0 +1,894 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
#use warnings;
|
||||
|
||||
use Sort::Naturally;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
no warnings 'uninitialized';
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require '/var/ipfire/network-functions.pl';
|
||||
require "/var/ipfire/location-functions.pl";
|
||||
require "/usr/lib/firewall/firewall-lib.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
my %hasettings=();
|
||||
my %virtualserver=();
|
||||
my %realserver=();
|
||||
my %icmptypes=();
|
||||
my %color=();
|
||||
my %defaultNetworks=();
|
||||
my %mainsettings=();
|
||||
my %ownnet=();
|
||||
my %fwfwd=();
|
||||
my %fwinp=();
|
||||
my %fwout=();
|
||||
my %netsettings=();
|
||||
my %optionsfw=();
|
||||
|
||||
my $errormessage;
|
||||
my $hint;
|
||||
my $update=0;
|
||||
my $configvs = "${General::swroot}/keepalived/configvs";
|
||||
my $configrs = "${General::swroot}/keepalived/configrs";
|
||||
my $fwoptions = "${General::swroot}/optionsfw/settings";
|
||||
|
||||
unless (-e $configvs) { &General::system("touch", "$configvs"); }
|
||||
unless (-e $configrs) { &General::system("touch", "$configrs"); }
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
&General::readhash("${General::swroot}/ethernet/settings", \%ownnet);
|
||||
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
|
||||
&General::readhash($fwoptions, \%optionsfw);
|
||||
|
||||
&Header::getcgihash(\%hasettings);
|
||||
&Header::showhttpheaders();
|
||||
&Header::openpage($Lang::tr{'fwhost menu'}, 1, '');
|
||||
&Header::openbigbox('100%', 'center');
|
||||
|
||||
#### JAVA SCRIPT ####
|
||||
print<<END;
|
||||
<script>
|
||||
var PROTOCOLS_WITH_PORTS = ["TCP", "UDP"];
|
||||
var update_protocol = function() {
|
||||
var protocol = \$("#protocol").val();
|
||||
|
||||
if (protocol === undefined)
|
||||
return;
|
||||
|
||||
// Check if we are dealing with a protocol, that knows ports.
|
||||
if (\$.inArray(protocol, PROTOCOLS_WITH_PORTS) >= 0) {
|
||||
\$("#PORT").show();
|
||||
\$("#PROTOKOLL").hide();
|
||||
} else {
|
||||
\$("#PORT").hide();
|
||||
\$("#PROTOKOLL").show();
|
||||
}
|
||||
};
|
||||
|
||||
\$(document).ready(function() {
|
||||
var protocol = \$("#protocol").val();
|
||||
\$("#protocol").change(update_protocol);
|
||||
update_protocol();
|
||||
// Automatically select radio buttons when corresponding
|
||||
// dropdown menu changes.
|
||||
\$("select").change(function() {
|
||||
var id = \$(this).attr("name");
|
||||
\$('#' + id).prop("checked", true);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
END
|
||||
|
||||
## ACTION ####
|
||||
# Update
|
||||
if ($hasettings{'ACTION'} eq 'updatevs' )
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
foreach my $key (keys %virtualserver)
|
||||
{
|
||||
if($virtualserver{$key}[0] eq $hasettings{'orgname'})
|
||||
{
|
||||
$hasettings{'orgname'} = $virtualserver{$key}[0];
|
||||
$hasettings{'orgip'} = $virtualserver{$key}[1];
|
||||
$hasettings{'orgsub'} = $virtualserver{$key}[2];
|
||||
$hasettings{'netremark'} = $virtualserver{$key}[3];
|
||||
$hasettings{'count'} = $virtualserver{$key}[4];
|
||||
delete $virtualserver{$key};
|
||||
|
||||
}
|
||||
}
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
$hasettings{'actualize'} = 'on';
|
||||
$hasettings{'ACTION'} = 'savevs';
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'updaters')
|
||||
{
|
||||
my ($ip,$subnet);
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
foreach my $key (keys %realserver)
|
||||
{
|
||||
if($realserver{$key}[0] eq $hasettings{'orgname'})
|
||||
{
|
||||
if ($realserver{$key}[1] eq 'ip'){
|
||||
($ip,$subnet) = split (/\//,$realserver{$key}[2]);
|
||||
}else{
|
||||
$ip = $realserver{$key}[2];
|
||||
}
|
||||
$hasettings{'orgip'} = $ip;
|
||||
delete $realserver{$key};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
}
|
||||
}
|
||||
$hasettings{'actualize'} = 'on';
|
||||
if($hasettings{'orgip'}){
|
||||
$hasettings{'ACTION'} = 'savers';
|
||||
}else{
|
||||
$hasettings{'ACTION'} = $Lang::tr{'fwhost newhost'};
|
||||
}
|
||||
}
|
||||
# save
|
||||
if ($hasettings{'ACTION'} eq 'savevs' )
|
||||
{
|
||||
my $needrules=0;
|
||||
if ($hasettings{'orgname'} eq ''){$hasettings{'orgname'}=$hasettings{'HOSTNAME'};}
|
||||
#check if all fields are set
|
||||
if ($hasettings{'HOSTNAME'} eq '' || $hasettings{'IP'} eq '' || $hasettings{'SUBNET'} eq '')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err empty'};
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}else{
|
||||
#convert ip if leading '0' exists
|
||||
$hasettings{'IP'} = &Network::ip_remove_zero($hasettings{'IP'});
|
||||
|
||||
#check valid ip
|
||||
if (!&General::validipandmask($hasettings{'IP'}."/".$hasettings{'SUBNET'}))
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err addr'};
|
||||
$hasettings{'BLK_HOST'} ='readonly';
|
||||
$hasettings{'NOCHECK'} ='false';
|
||||
$hasettings{'error'} ='on';
|
||||
}
|
||||
#check remark
|
||||
if ($hasettings{'NETREMARK'} ne '' && !&validremark($hasettings{'NETREMARK'})){
|
||||
$errormessage=$Lang::tr{'fwhost err remark'};
|
||||
$hasettings{'error'} ='on';
|
||||
}
|
||||
#check if subnet is sigle host
|
||||
if(&General::iporsubtocidr($hasettings{'SUBNET'}) eq '32')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err sub32'};
|
||||
}
|
||||
if($hasettings{'error'} ne 'on'){
|
||||
my $fullip="$hasettings{'IP'}/".&General::iporsubtocidr($hasettings{'SUBNET'});
|
||||
$errormessage=$errormessage.&General::checksubnets($hasettings{'HOSTNAME'},$fullip,"","exact");
|
||||
}
|
||||
#only check plausi when no error till now
|
||||
if (!$errormessage){
|
||||
&plausicheck("editvs");
|
||||
}
|
||||
if($hasettings{'actualize'} eq 'on' && $hasettings{'newnet'} ne 'on' && $errormessage)
|
||||
{
|
||||
$hasettings{'actualize'} = '';
|
||||
my $key = &General::findhasharraykey (\%virtualserver);
|
||||
foreach my $i (0 .. 3) { $virtualserver{$key}[$i] = "";}
|
||||
$virtualserver{$key}[0] = $hasettings{'orgname'} ;
|
||||
$virtualserver{$key}[1] = $hasettings{'orgip'} ;
|
||||
$virtualserver{$key}[2] = $hasettings{'orgsub'};
|
||||
$virtualserver{$key}[3] = $hasettings{'orgnetremark'};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
undef %virtualserver;
|
||||
}
|
||||
if (!$errormessage){
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
if ($hasettings{'ACTION'} eq 'updatevs'){
|
||||
if ($hasettings{'update'} == '0'){
|
||||
foreach my $key (keys %virtualserver) {
|
||||
if($virtualserver{$key}[0] eq $hasettings{'orgname'}){
|
||||
delete $virtualserver{$key};
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#get count if actualize is 'on'
|
||||
if($hasettings{'actualize'} eq 'on'){
|
||||
$hasettings{'actualize'} = '';
|
||||
#check if we need to reload rules
|
||||
if($hasettings{'orgip'} ne $hasettings{'IP'}){
|
||||
$needrules='on';
|
||||
}
|
||||
if ($hasettings{'orgname'} ne $hasettings{'HOSTNAME'}){
|
||||
}
|
||||
}
|
||||
my $key = &General::findhasharraykey (\%virtualserver);
|
||||
foreach my $i (0 .. 3) { $virtualserver{$key}[$i] = "";}
|
||||
$hasettings{'SUBNET'} = &General::iporsubtocidr($hasettings{'SUBNET'});
|
||||
$virtualserver{$key}[0] = $hasettings{'HOSTNAME'};
|
||||
$virtualserver{$key}[1] = &General::getnetworkip($hasettings{'IP'},$hasettings{'SUBNET'}) ;
|
||||
$virtualserver{$key}[2] = &General::iporsubtodec($hasettings{'SUBNET'}) ;
|
||||
$virtualserver{$key}[3] = $hasettings{'NETREMARK'};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
$hasettings{'IP'}=$hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
undef %virtualserver;
|
||||
$hasettings{'HOSTNAME'}='';
|
||||
$hasettings{'IP'}='';
|
||||
$hasettings{'SUBNET'}='';
|
||||
$hasettings{'NETREMARK'}='';
|
||||
#check if an edited net affected groups and need to reload rules
|
||||
if ($needrules eq 'on'){
|
||||
&General::firewall_config_changed();
|
||||
}
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}else{
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'savers')
|
||||
{
|
||||
my $needrules=0;
|
||||
if ($hasettings{'orgname'} eq ''){$hasettings{'orgname'}=$hasettings{'HOSTNAME'};}
|
||||
$hasettings{'SUBNET'}='32';
|
||||
#check if all fields are set
|
||||
if ($hasettings{'HOSTNAME'} eq '' || $hasettings{'IP'} eq '' || $hasettings{'SUBNET'} eq '')
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err empty'};
|
||||
$hasettings{'ACTION'} = 'editrs';
|
||||
}else{
|
||||
if($hasettings{'IP'}=~/^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$/){
|
||||
$hasettings{'type'} = 'mac';
|
||||
}elsif($hasettings{'IP'}=~/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/){
|
||||
$hasettings{'type'} = 'ip';
|
||||
}else{
|
||||
$hasettings{'type'} = '';
|
||||
$errormessage=$Lang::tr{'fwhost err ipmac'};
|
||||
}
|
||||
#check remark
|
||||
if ($hasettings{'HOSTREMARK'} ne '' && !&validremark($hasettings{'HOSTREMARK'})){
|
||||
$errormessage=$Lang::tr{'fwhost err remark'};
|
||||
}
|
||||
#CHECK IP-PART
|
||||
if ($hasettings{'type'} eq 'ip'){
|
||||
#convert ip if leading '0' exists
|
||||
$hasettings{'IP'} = &Network::ip_remove_zero($hasettings{'IP'});
|
||||
|
||||
#check for subnet
|
||||
if (rindex($hasettings{'IP'},'/') eq '-1' ){
|
||||
if($hasettings{'type'} eq 'ip' && !&General::validipandmask($hasettings{'IP'}."/32"))
|
||||
{
|
||||
$errormessage.=$errormessage.$Lang::tr{'fwhost err ip'};
|
||||
$hasettings{'error'}='on';
|
||||
}
|
||||
}elsif(rindex($hasettings{'IP'},'/') ne '-1' ){
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err ipwithsub'};
|
||||
$hasettings{'error'}='on';
|
||||
}
|
||||
#check if net or broadcast
|
||||
my @tmp= split (/\./,$hasettings{'IP'});
|
||||
if (($tmp[3] eq "0") || ($tmp[3] eq "255")){
|
||||
$errormessage=$Lang::tr{'fwhost err hostip'};
|
||||
}
|
||||
}
|
||||
#only check plausi when no error till now
|
||||
if (!$errormessage){
|
||||
&plausicheck("editrs");
|
||||
}
|
||||
if($hasettings{'actualize'} eq 'on' && $hasettings{'newrs'} ne 'on' && $errormessage){
|
||||
$hasettings{'actualize'} = '';
|
||||
my $key = &General::findhasharraykey (\%realserver);
|
||||
foreach my $i (0 .. 3) { $realserver{$key}[$i] = "";}
|
||||
$realserver{$key}[0] = $hasettings{'orgname'} ;
|
||||
$realserver{$key}[1] = $hasettings{'type'} ;
|
||||
if($realserver{$key}[1] eq 'ip'){
|
||||
$realserver{$key}[2] = $hasettings{'orgip'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
}else{
|
||||
$realserver{$key}[2] = $hasettings{'orgip'};
|
||||
}
|
||||
$realserver{$key}[3] = $hasettings{'orgremark'};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
undef %realserver;
|
||||
}
|
||||
if (!$errormessage){
|
||||
#get count if host was edited
|
||||
if($hasettings{'actualize'} eq 'on'){
|
||||
if($hasettings{'orgip'} ne $hasettings{'IP'}){
|
||||
$needrules='on';
|
||||
}
|
||||
if($hasettings{'orgname'} ne $hasettings{'HOSTNAME'}){
|
||||
#check if we need to update firewallrules
|
||||
}
|
||||
}
|
||||
my $key = &General::findhasharraykey (\%realserver);
|
||||
foreach my $i (0 .. 3) { $realserver{$key}[$i] = "";}
|
||||
$realserver{$key}[0] = $hasettings{'HOSTNAME'} ;
|
||||
$realserver{$key}[1] = $hasettings{'type'} ;
|
||||
if ($hasettings{'type'} eq 'ip'){
|
||||
$realserver{$key}[2] = $hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'});
|
||||
}else{
|
||||
$realserver{$key}[2] = $hasettings{'IP'};
|
||||
}
|
||||
$realserver{$key}[3] = $hasettings{'HOSTREMARK'};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
undef %realserver;
|
||||
$hasettings{'HOSTNAME'}='';
|
||||
$hasettings{'IP'}='';
|
||||
$hasettings{'type'}='';
|
||||
$hasettings{'HOSTREMARK'}='';
|
||||
#check if we need to update rules while host was edited
|
||||
if($needrules eq 'on'){
|
||||
&General::firewall_config_changed();
|
||||
}
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}else{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
}
|
||||
}
|
||||
# edit
|
||||
if ($hasettings{'ACTION'} eq 'editvs')
|
||||
{
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'editrs')
|
||||
{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
# reset
|
||||
if ($hasettings{'ACTION'} eq 'resetvs')
|
||||
{
|
||||
$hasettings{'HOSTNAME'} ="";
|
||||
$hasettings{'IP'} ="";
|
||||
$hasettings{'SUBNET'} ="";
|
||||
&showmenu;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'resetrs')
|
||||
{
|
||||
$hasettings{'HOSTNAME'} ="";
|
||||
$hasettings{'IP'} ="";
|
||||
$hasettings{'type'} ="";
|
||||
&showmenu;
|
||||
}
|
||||
# delete
|
||||
if ($hasettings{'ACTION'} eq 'delnet')
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
foreach my $key (keys %virtualserver) {
|
||||
if($hasettings{'key'} eq $virtualserver{$key}[0]){
|
||||
delete $virtualserver{$key};
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
last;
|
||||
}
|
||||
}
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq 'delhost')
|
||||
{
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
foreach my $key (keys %realserver) {
|
||||
if($hasettings{'key'} eq $realserver{$key}[0]){
|
||||
delete $realserver{$key};
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
last;
|
||||
}
|
||||
}
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'fwhost newnet'})
|
||||
{
|
||||
&addvs;
|
||||
&viewtablevs;
|
||||
}
|
||||
if ($hasettings{'ACTION'} eq $Lang::tr{'fwhost newhost'})
|
||||
{
|
||||
&addrs;
|
||||
&viewtablers;
|
||||
}
|
||||
### VIEW ###
|
||||
if($hasettings{'ACTION'} eq '')
|
||||
{
|
||||
&showmenu;
|
||||
}
|
||||
### FUNCTIONS ###
|
||||
sub showmenu {
|
||||
&Header::openbox('100%', 'left',);
|
||||
print "$Lang::tr{'fwhost welcome'}";
|
||||
print<<END;
|
||||
<br><br><table border='0' width='100%'>
|
||||
<tr><td><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newnet'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newhost'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newgrp'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newlocationgrp'}' ></form></td>
|
||||
<td align='right'><form method='post'><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservice'}' ><input type='submit' name='ACTION' value='$Lang::tr{'fwhost newservicegrp'}' ></form></td></tr>
|
||||
<tr><td colspan='6'></td></tr></table>
|
||||
END
|
||||
&Header::closebox();
|
||||
|
||||
}
|
||||
# Add
|
||||
sub addvs {
|
||||
&error;
|
||||
&showmenu;
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost addnet'});
|
||||
$hasettings{'orgname'} = $hasettings{'HOSTNAME'};
|
||||
$hasettings{'orgnetremark'} = $hasettings{'NETREMARK'};
|
||||
|
||||
print <<END;
|
||||
<table border='0' width='100%'>
|
||||
<tr>
|
||||
<td width='15%'>$Lang::tr{'name'}:</td>
|
||||
<td>
|
||||
<form method='post'>
|
||||
<input type='TEXT' name='HOSTNAME' id='textbox1' value='$hasettings{'HOSTNAME'}' $hasettings{'BLK_HOST'} size='20'>
|
||||
<script>document.getElementById('textbox1').focus()</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'fwhost netaddress'}:</td>
|
||||
<td><input type='TEXT' name='IP' value='$hasettings{'IP'}' $hasettings{'BLK_IP'} size='20' maxlength='15'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'netmask'}:</td>
|
||||
<td><input type='TEXT' name='SUBNET' value='$hasettings{'SUBNET'}' $hasettings{'BLK_IP'} size='20' maxlength='15'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$Lang::tr{'remark'}:</td>
|
||||
<td><input type='TEXT' name='NETREMARK' value='$hasettings{'NETREMARK'}' style='width: 98.5%;'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='6'><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
END
|
||||
|
||||
if ($hasettings{'ACTION'} eq 'editvs' || $hasettings{'error'} eq 'on') {
|
||||
print <<END;
|
||||
<td colspan='6' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'update'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='updatevs'>
|
||||
<input type='hidden' name='orgnetremark' value='$hasettings{'orgnetremark'}'>
|
||||
<input type='hidden' name='orgname' value='$hasettings{'orgname'}'>
|
||||
<input type='hidden' name='update' value='on'>
|
||||
<input type='hidden' name='newnet' value='$hasettings{'newnet'}'>
|
||||
</td>
|
||||
</form>
|
||||
END
|
||||
} else {
|
||||
print <<END;
|
||||
<td colspan='6' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'save'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='savevs'>
|
||||
<input type='hidden' name='newnet' value='on'>
|
||||
</td>
|
||||
</form>
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
<form method='post' style='display:inline'>
|
||||
<input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'>
|
||||
<input type='hidden' name='ACTION' value='resetvs'>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
sub addrs {
|
||||
&error;
|
||||
&showmenu;
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost addhost'});
|
||||
|
||||
$hasettings{'orgname'} = $hasettings{'HOSTNAME'};
|
||||
$hasettings{'orgremark'} = $hasettings{'HOSTREMARK'};
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td>$Lang::tr{'name'}:</td>
|
||||
<td>
|
||||
<form method='post' style='display:inline;'>
|
||||
<input type='TEXT' name='HOSTNAME' id='textbox1' value='$hasettings{'HOSTNAME'}' $hasettings{'BLK_HOST'} size='20'>
|
||||
<script>document.getElementById('textbox1').focus()</script>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>IP/MAC:</td>
|
||||
<td><input type='TEXT' name='IP' value='$hasettings{'IP'}' $hasettings{'BLK_IP'} size='20' maxlength='17'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='10%'>$Lang::tr{'remark'}:</td>
|
||||
<td><input type='TEXT' name='HOSTREMARK' value='$hasettings{'HOSTREMARK'}' style='width:98%;'></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan='5'><br></td>
|
||||
</tr>
|
||||
<tr>
|
||||
END
|
||||
|
||||
if ($hasettings{'ACTION'} eq 'editrs' || $hasettings{'error'} eq 'on') {
|
||||
print <<END;
|
||||
<td colspan='4' align='right'>
|
||||
<input type='submit' value='$Lang::tr{'update'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='updaters'>
|
||||
<input type='hidden' name='orgremark' value='$hasettings{'orgremark'}'>
|
||||
<input type='hidden' name='orgname' value='$hasettings{'orgname'}'>
|
||||
<input type='hidden' name='update' value='on'>
|
||||
<input type='hidden' name='newrs' value='$hasettings{'newrs'}'>
|
||||
</form>
|
||||
END
|
||||
} else {
|
||||
print <<END;
|
||||
<td colspan='4' align='right'>
|
||||
<input type='submit' name='savers' value='$Lang::tr{'save'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='savers'/>
|
||||
<input type='hidden' name='newrs' value='on'>
|
||||
</form>
|
||||
END
|
||||
}
|
||||
|
||||
print <<END;
|
||||
<form method='post' style='display:inline'>
|
||||
<input type='submit' value='$Lang::tr{'fwhost back'}' style='min-width:100px;'/>
|
||||
<input type='hidden' name='ACTION' value='resetrs'>
|
||||
</form></td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# View
|
||||
|
||||
sub viewtablers {
|
||||
if (!-z $configrs) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost cust addr'});
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
|
||||
if (!keys %realserver) {
|
||||
print "<center><b>$Lang::tr{'fwhost empty'}</b>";
|
||||
} else {
|
||||
print <<END;
|
||||
<table width='100%' cellspacing='0' class='tbl'>
|
||||
<tr>
|
||||
<th align='center'><b>$Lang::tr{'name'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'fwhost ip_mac'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th></th>
|
||||
<th width='3%'></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $col = '';
|
||||
|
||||
foreach my $key (sort { ncmp($realserver{$a}[0], $realserver{$b}[0]) } keys %realserver) {
|
||||
if (($hasettings{'ACTION'} eq 'editrs' || $hasettings{'error'}) && $hasettings{'HOSTNAME'} eq $realserver{$key}[0]) {
|
||||
print "<tr>";
|
||||
$col = "bgcolor='${Header::colouryellow}'";
|
||||
} elsif ($count % 2) {
|
||||
print "<tr>";
|
||||
$col = "bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
$col = "bgcolor='$color{'color22'}'";
|
||||
print "<tr>";
|
||||
}
|
||||
|
||||
my ($ip, $sub) = split(/\//, $realserver{$key}[2]);
|
||||
|
||||
print "<td width='20%' align='center' $col>$realserver{$key}[0]</td>";
|
||||
print "<td width='20%' align='center' $col>" . &getcolor($ip) . "</td>";
|
||||
print "<td width='50%' align='center' $col>$realserver{$key}[3]</td>";
|
||||
|
||||
print <<END;
|
||||
<td width='1%' $col>
|
||||
<form method='post'>
|
||||
<input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='editrs' />
|
||||
<input type='hidden' name='HOSTNAME' value='$realserver{$key}[0]' />
|
||||
<input type='hidden' name='IP' value='$ip' />
|
||||
<input type='hidden' name='type' value='$realserver{$key}[1]' />
|
||||
<input type='hidden' name='HOSTREMARK' value='$realserver{$key}[3]' />
|
||||
</form>
|
||||
</td>
|
||||
END
|
||||
|
||||
print "<td width='1%' $col><form method='post'>";
|
||||
print "<input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />";
|
||||
print "<input type='hidden' name='ACTION' value='delhost' />";
|
||||
print "<input type='hidden' name='key' value='$realserver{$key}[0]' />";
|
||||
print "</form></td></tr>";
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
|
||||
sub viewtablevs {
|
||||
if (!-z $configvs) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost cust net'});
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
|
||||
if (!keys %virtualserver) {
|
||||
print "<center><b>$Lang::tr{'fwhost empty'}</b>";
|
||||
} else {
|
||||
print <<END;
|
||||
<table width='100%' cellspacing='0' class='tbl'>
|
||||
<tr>
|
||||
<th align='center'><b>$Lang::tr{'name'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'fwhost netaddress'}</b></th>
|
||||
<th align='center'><b>$Lang::tr{'remark'}</b></th>
|
||||
<th></th>
|
||||
<th width='3%'></th>
|
||||
</tr>
|
||||
END
|
||||
}
|
||||
|
||||
my $count = 0;
|
||||
my $col = '';
|
||||
|
||||
foreach my $key (sort { ncmp($a, $b) } keys %virtualserver) {
|
||||
if ($hasettings{'ACTION'} eq 'editvs' && $hasettings{'HOSTNAME'} eq $virtualserver{$key}[0]) {
|
||||
print " <tr>";
|
||||
$col = "bgcolor='${Header::colouryellow}'";
|
||||
} elsif ($count % 2) {
|
||||
$col = "bgcolor='$color{'color20'}'";
|
||||
print " <tr>";
|
||||
} else {
|
||||
$col = "bgcolor='$color{'color22'}'";
|
||||
print " <tr>";
|
||||
}
|
||||
|
||||
my $colnet = "$virtualserver{$key}[1]/" . &General::subtocidr($virtualserver{$key}[2]);
|
||||
|
||||
print "<td width='20%' align='center' $col><form method='post'>$virtualserver{$key}[0]</td>";
|
||||
print "<td width='15%' align='center' $col>" . &getcolor($colnet) . "</td>";
|
||||
print "<td width='40%' align='center' $col>$virtualserver{$key}[3]</td>";
|
||||
|
||||
print <<END;
|
||||
<td width='1%' $col>
|
||||
<input type='image' src='/images/edit.gif' align='middle' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='ACTION' value='editvs' />
|
||||
<input type='hidden' name='HOSTNAME' value='$virtualserver{$key}[0]' />
|
||||
<input type='hidden' name='IP' value='$virtualserver{$key}[1]' />
|
||||
<input type='hidden' name='SUBNET' value='$virtualserver{$key}[2]' />
|
||||
<input type='hidden' name='NETREMARK' value='$virtualserver{$key}[3]' />
|
||||
</td></form>
|
||||
END
|
||||
|
||||
print "<td width='1%' $col><form method='post'>";
|
||||
print "<input type='image' src='/images/delete.gif' align='middle' alt='$Lang::tr{'delete'}' title='$Lang::tr{'delete'}' />";
|
||||
print "<input type='hidden' name='ACTION' value='delnet' />";
|
||||
print "<input type='hidden' name='key' value='$virtualserver{$key}[0]' />";
|
||||
print "</form></td></tr>";
|
||||
|
||||
$count++;
|
||||
}
|
||||
|
||||
print "</table>";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
|
||||
sub getcolor
|
||||
{
|
||||
my $c=shift;
|
||||
my $sip;
|
||||
my $scidr;
|
||||
my $tdcolor='';
|
||||
#Check if MAC
|
||||
if (&General::validmac($c)){ return $c;}
|
||||
|
||||
#Check if we got a full IP with subnet then split it
|
||||
if($c =~ /^(.*?)\/(.*?)$/){
|
||||
($sip,$scidr) = split ("/",$c);
|
||||
}else{
|
||||
$sip=$c;
|
||||
}
|
||||
|
||||
#Now check if IP is part of ORANGE,BLUE or GREEN
|
||||
if ( &Header::orange_used() && &General::IpInSubnet($sip,$netsettings{'ORANGE_ADDRESS'},$netsettings{'ORANGE_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourorange;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ( &General::IpInSubnet($sip,$netsettings{'GREEN_ADDRESS'},$netsettings{'GREEN_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourgreen;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ( &Header::blue_used() && &General::IpInSubnet($sip,$netsettings{'BLUE_ADDRESS'},$netsettings{'BLUE_NETMASK'})){
|
||||
$tdcolor="<font style='color: $Header::colourblue;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
if ("$sip/$scidr" eq "0.0.0.0/0"){
|
||||
$tdcolor="<font style='color: $Header::colourred;'>$c</font>";
|
||||
return $tdcolor;
|
||||
}
|
||||
|
||||
return "$c";
|
||||
}
|
||||
|
||||
|
||||
sub checkname
|
||||
{
|
||||
my %hash=%{(shift)};
|
||||
foreach my $key (keys %hash) {
|
||||
if($hash{$key}[0] eq $hasettings{'HOSTNAME'}){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
sub checkip
|
||||
{
|
||||
|
||||
my %hash=%{(shift)};
|
||||
my $a=shift;
|
||||
foreach my $key (keys %hash) {
|
||||
if($hash{$key}[$a] eq $hasettings{'IP'}."/".&General::iporsubtodec($hasettings{'SUBNET'})){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
sub error
|
||||
{
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<class name='base'>$errormessage\n";
|
||||
print " </class>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
sub hint
|
||||
{
|
||||
if ($hint) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'fwhost hint'});
|
||||
print "<class name='base'>$hint\n";
|
||||
print " </class>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
}
|
||||
sub get_name
|
||||
{
|
||||
my $val=shift;
|
||||
&General::setup_default_networks(\%defaultNetworks);
|
||||
foreach my $network (sort keys %defaultNetworks)
|
||||
{
|
||||
return "$network" if ($val eq $defaultNetworks{$network}{'NAME'});
|
||||
}
|
||||
}
|
||||
sub gethostcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
}
|
||||
sub getnetcount
|
||||
{
|
||||
my $searchstring=shift;
|
||||
}
|
||||
sub plausicheck
|
||||
{
|
||||
my $edit=shift;
|
||||
#check hostname
|
||||
if (!&validhostname($hasettings{'HOSTNAME'}))
|
||||
{
|
||||
$errormessage=$errormessage.$Lang::tr{'fwhost err name'};
|
||||
$hasettings{'BLK_IP'}='readonly';
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if network with this name already exists
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
if (!&checkname(\%virtualserver))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err netexist'};
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if network ip already exists
|
||||
if (!&checkip(\%virtualserver,1))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err net'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if host with this name already exists
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
if (!&checkname(\%realserver))
|
||||
{
|
||||
$errormessage.="<br>".$Lang::tr{'fwhost err hostexist'};
|
||||
$hasettings{'HOSTNAME'} = $hasettings{'orgname'};
|
||||
if ($hasettings{'update'} eq 'on'){$hasettings{'ACTION'}=$edit;}
|
||||
}
|
||||
#check if host with this ip already exists
|
||||
if (!&checkip(\%realserver,2))
|
||||
{
|
||||
$errormessage=$errormessage."<br>".$Lang::tr{'fwhost err ipcheck'};
|
||||
}
|
||||
return;
|
||||
}
|
||||
sub decrease
|
||||
{
|
||||
&General::readhasharray("$configvs", \%virtualserver);
|
||||
&General::readhasharray("$configrs", \%realserver);
|
||||
&General::writehasharray("$configvs", \%virtualserver);
|
||||
&General::writehasharray("$configrs", \%realserver);
|
||||
}
|
||||
sub validhostname
|
||||
{
|
||||
# Checks a hostname against RFC1035
|
||||
my $hostname = $_[0];
|
||||
|
||||
# Each part should be at least two characters in length
|
||||
# but no more than 63 characters
|
||||
if (length ($hostname) < 1 || length ($hostname) > 63) {
|
||||
return 0;}
|
||||
# Only valid characters are a-z, A-Z, 0-9 and -
|
||||
if ($hostname !~ /^[a-zA-ZäöüÖÄÜ0-9-_.;()\/\s]*$/) {
|
||||
return 0;}
|
||||
# First character can only be a letter or a digit
|
||||
if (substr ($hostname, 0, 1) !~ /^[a-zA-ZöäüÖÄÜ0-9]*$/) {
|
||||
return 0;}
|
||||
# Last character can only be a letter or a digit
|
||||
if (substr ($hostname, -1, 1) !~ /^[a-zA-ZöäüÖÄÜ0-9()]*$/) {
|
||||
return 0;}
|
||||
return 1;
|
||||
}
|
||||
sub validremark
|
||||
{
|
||||
# Checks a hostname against RFC1035
|
||||
my $remark = $_[0];
|
||||
# Each part should be at least two characters in length
|
||||
# but no more than 63 characters
|
||||
if (length ($remark) < 1 || length ($remark) > 255) {
|
||||
return 0;}
|
||||
# Only valid characters are a-z, A-Z, 0-9 and -
|
||||
if ($remark !~ /^[a-zäöüA-ZÖÄÜ0-9-.:;\|_()\/\s]*$/) {
|
||||
return 0;}
|
||||
# First character can only be a letter or a digit
|
||||
if (substr ($remark, 0, 1) !~ /^[a-zäöüA-ZÖÄÜ0-9]*$/) {
|
||||
return 0;}
|
||||
# Last character can only be a letter or a digit
|
||||
if (substr ($remark, -1, 1) !~ /^[a-zöäüA-ZÖÄÜ0-9.:;_)]*$/) {
|
||||
return 0;}
|
||||
return 1;
|
||||
}
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
469
html/cgi-bin/loxilb.cgi
Normal file
@@ -0,0 +1,469 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2020 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
use IO::Socket;
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/location-functions.pl";
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
my %settings=();
|
||||
my %checked=();
|
||||
my $errormessage='';
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
my $loxilbsettingfile = "${General::swroot}/loxilb/settings";
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
|
||||
# Read configuration file.
|
||||
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
$settings{'ENABLE_LOXILB'} = 'off';
|
||||
$settings{'ACTION'} = '';
|
||||
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
$settings{'virtualIP'} = '';
|
||||
$settings{'interface'} = '';
|
||||
my @nosaved=('virtualIP','interface', 'KEY1', 'SORT_virtualIPLIST');
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^virtualIP';
|
||||
$settings{'SORT_virtualIPLIST'} = 'virtualIP';
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'save'})
|
||||
{
|
||||
|
||||
map (delete ($settings{$_}) ,(@nosaved));
|
||||
&General::writehash("$loxilbsettingfile", \%settings);
|
||||
|
||||
if ($settings{'ENABLE_LOXILB'} eq 'on') {
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/loxilb/enableloxilb");
|
||||
&General::system('/usr/local/bin/loxilbctrl', 'start');
|
||||
} else {
|
||||
&General::system('/usr/local/bin/loxilbctrl', 'stop');
|
||||
unlink "${General::swroot}/loxilb/enableloxilb";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validipandmask($settings{'virtualIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[1] ='' unless defined $temp[1]; # interface
|
||||
#Same ip already used?
|
||||
if($temp[0] eq $settings{'virtualIP'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'virtualIP'},$settings{'interface'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'virtualIP'},$settings{'interface'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
}
|
||||
|
||||
&CreateIP(%settings);
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'virtualIP'}=$temp[0];
|
||||
$settings{'interface'}=$temp[1];
|
||||
|
||||
&DeleteIP(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$loxilbipfile") or die "$loxilbipfile open error";
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_virtualIPLIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_virtualIPLIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'virtualIP'} = '';
|
||||
$settings{'interface'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb'}, 1, '');
|
||||
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>\n";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
# Read configuration file.
|
||||
&General::readhash("$loxilbsettingfile", \%settings);
|
||||
|
||||
# Checkbox pre-selection.
|
||||
my $checked;
|
||||
if ($settings{'ENABLE_LOXILB'} eq "on") {
|
||||
$checked = "checked='checked'";
|
||||
}
|
||||
|
||||
my $sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourred}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'stopped'}</font></b></td></tr></table>";
|
||||
|
||||
my @status = &General::system_output('/usr/local/bin/loxilbctrl', 'status');
|
||||
|
||||
if (grep(/is running/, @status)){
|
||||
$sactive = "<table cellpadding='2' cellspacing='0' bgcolor='${Header::colourgreen}' width='50%'><tr><td align='center'><b><font color='#FFFFFF'>$Lang::tr{'running'}</font></b></td></tr></table>";
|
||||
}
|
||||
|
||||
&Header::openbox('100%', 'center', $Lang::tr{'loxilb status'});
|
||||
|
||||
print <<END;
|
||||
<table width='100%'>
|
||||
<form method='POST' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<td width='25%'> </td>
|
||||
<tr><td class='boldbase'>$Lang::tr{'loxilb server status'}</td>
|
||||
<td align='left'>$sactive</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width='50%' class='boldbase'>$Lang::tr{'loxilb enable'}
|
||||
<td><input type='checkbox' name='ENABLE_LOXILB' $checked></td>
|
||||
<td align='center'><input type='submit' name='ACTION' value='$Lang::tr{'save'}'></td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
print "</form> </table>\n";
|
||||
|
||||
&Header::closebox();
|
||||
#
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb ip add'});
|
||||
}
|
||||
|
||||
my @INTERFACES = ("red0", "green0");
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb ip virtualIP'}: </td>
|
||||
<td><input type='text' name='virtualIP' value='$settings{'virtualIP'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb ip interface'}: </td>
|
||||
<td>
|
||||
<select name='interface' id='interface' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@INTERFACES) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'interface'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb ip entries'});
|
||||
|
||||
print <<END;
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?virtualIP'><b>$Lang::tr{'loxilb ip virtualIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?interface'><b>$Lang::tr{'loxilb ip interface'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[1] ='' unless defined $temp[1]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END;
|
||||
<td align='center' $col>$temp[0]</td>
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END;
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
|
||||
&Header::closepage();
|
||||
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_virtualIPLIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_virtualIPLIST'},0,length($settings{'SORT_virtualIPLIST'})-3);
|
||||
if ($qs eq 'virtualIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_virtualIPLIST'};
|
||||
if ($qs eq 'virtualIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'virtualIP',$temp[0],'interface',$temp[1]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$loxilbipfile") or die "$loxilbipfile open error";
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{virtualIP},$entries{$entry}->{interface}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$loxilbipfile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub manageIP {
|
||||
my ($action, %settings) = @_;
|
||||
|
||||
# Initialize variables
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
|
||||
my $ip = $settings{'virtualIP'};
|
||||
my $interface = $settings{'interface'};
|
||||
|
||||
push(@loxicmd_options, $action, "ip", $ip, $interface);
|
||||
|
||||
#debug and display output in UI
|
||||
#my @output = &General::system_output($command, @loxicmd_options);
|
||||
#$errormessage = join('', @output);
|
||||
&General::system($command, @loxicmd_options);
|
||||
|
||||
}
|
||||
|
||||
sub CreateIP {
|
||||
my (%settings) = @_;
|
||||
manageIP("create", %settings);
|
||||
}
|
||||
|
||||
sub DeleteIP {
|
||||
my (%settings) = @_;
|
||||
manageIP("delete", %settings);
|
||||
}
|
||||
|
||||
699
html/cgi-bin/loxilbconfig.cgi
Normal file
@@ -0,0 +1,699 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2011 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
# Files used
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
our $datafile = "${General::swroot}/loxilb/lbconfig"; #(our: used in subroutine)
|
||||
my $loxilbipfile = "${General::swroot}/loxilb/ipconfigfile";
|
||||
my $redfile = "${General::swroot}/red/local-ipaddress";
|
||||
|
||||
our @REDIP = ();
|
||||
our @IPFILE = ();
|
||||
|
||||
if (open(FILE, "$redfile")) {
|
||||
@REDIP = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
if (open(FILE, "$loxilbipfile")) {
|
||||
@IPFILE = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
our %settings = ();
|
||||
|
||||
$settings{'EN'} = ''; # reuse for dummy field in position zero
|
||||
$settings{'NAME'} = '';
|
||||
$settings{'EXTIP'} = '';
|
||||
$settings{'PORT'} = '';
|
||||
$settings{'PROTO'} = '';
|
||||
$settings{'SEL'} = '';
|
||||
$settings{'MODE'} = '';
|
||||
$settings{'ENDPOINTS'} = '';
|
||||
$settings{'EPORT'} = '';
|
||||
$settings{'MONITOR'} = '';
|
||||
my @nosaved=('EN','NAME','EXTIP','PORT','PROTO','SEL','MODE','ENDPOINTS','EPORT','MONITOR'); # List here ALL setting2 fields. Mandatory
|
||||
|
||||
$settings{'ACTION'} = ''; # add/edit/remove
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^NAME';
|
||||
$settings{'SORT_NAMELIST'} = 'NAME';
|
||||
my $errormessage = '';
|
||||
my $warnmessage = '';
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
###############
|
||||
# DEBUG DEBUG
|
||||
#&Header::openbox('100%', 'left', 'DEBUG');
|
||||
#my $debugCount = 0;
|
||||
#foreach my $line (sort keys %settings) {
|
||||
#print "$line = $settings{$line}<br />\n";
|
||||
# $debugCount++;
|
||||
#}
|
||||
#print " Count: $debugCount\n";
|
||||
#&Header::closebox();
|
||||
# DEBUG DEBUG
|
||||
###############
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$datafile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
## Settings1 Box not used...
|
||||
&General::readhash("${General::swroot}/main/settings", \%settings);
|
||||
|
||||
|
||||
## Now manipulate the multi-line list with Settings2
|
||||
# Basic actions are:
|
||||
# toggle the check box
|
||||
# add/update a new line
|
||||
# begin editing a line
|
||||
# remove a line
|
||||
|
||||
|
||||
# Toggle enable/disable field. Field is in second position
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
|
||||
#move out new line
|
||||
chomp(@current[$settings{'KEY1'}]);
|
||||
my @temp = split(/\,/,@current[$settings{'KEY1'}]);
|
||||
|
||||
$temp[0] = $temp[0] ne '' ? '' : 'on'; # Toggle the field
|
||||
@current[$settings{'KEY1'}] = join (',',@temp)."\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
|
||||
#Save current
|
||||
open(FILE, ">$datafile") or die 'loxilb lbconfig datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
|
||||
# Rebuild configuration file
|
||||
#&BuildConfiguration;
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validip($settings{'EXTIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'};
|
||||
}
|
||||
|
||||
if ($settings{'EXTIP'} =~ /^0\.0\.0\.0/){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." - 0.0.0.0";
|
||||
}
|
||||
if ($settings{'NAME'} eq ''){
|
||||
$errormessage = "LB Name: ".$Lang::tr{'loxilb empty'};
|
||||
}
|
||||
|
||||
# Escape input in REMARK field
|
||||
$settings{'NAME'} = &Header::escape($settings{'NAME'});
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
#Same ip already used?
|
||||
if($temp[1] eq $settings{'NAME'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'EN'},$settings{'NAME'},$settings{'EXTIP'},$settings{'PORT'},$settings{'PROTO'},$settings{'SEL'},$settings{'MODE'},$settings{'ENDPOINTS'},$settings{'EPORT'},$settings{'MONITOR'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'EN'},$settings{'NAME'},$settings{'EXTIP'},$settings{'PORT'},$settings{'PROTO'},$settings{'SEL'},$settings{'MODE'},$settings{'ENDPOINTS'},$settings{'EPORT'},$settings{'MONITOR'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
}
|
||||
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateLB(%settings);
|
||||
}
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {
|
||||
#move out new line
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'NAME'}=$temp[1];
|
||||
$settings{'EXTIP'}=$temp[2];
|
||||
$settings{'PORT'}=$temp[3];
|
||||
$settings{'PROTO'}=$temp[4];
|
||||
$settings{'SEL'}=$temp[5];
|
||||
$settings{'MODE'}=$temp[6];
|
||||
$settings{'ENDPOINTS'}=$temp[7];
|
||||
$settings{'EPORT'}=$temp[8];
|
||||
$settings{'MONITOR'}=$temp[9];
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateLB(%settings);
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'NAME'}=$temp[1];
|
||||
$settings{'EXTIP'}=$temp[2];
|
||||
$settings{'PORT'}=$temp[3];
|
||||
$settings{'PROTO'}=$temp[4];
|
||||
$settings{'SEL'}=$temp[5];
|
||||
$settings{'MODE'}=$temp[6];
|
||||
$settings{'ENDPOINTS'}=$temp[7];
|
||||
$settings{'EPORT'}=$temp[8];
|
||||
$settings{'MONITOR'}=$temp[9];
|
||||
&DeleteLB(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$datafile") or die 'route datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
&General::log($Lang::tr{'loxilb lb config changed'});
|
||||
|
||||
#&BuildConfiguration; # then re-build conf which use new data
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_NAMELIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_NAMELIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'EN'} = 'on';
|
||||
$settings{'NAME'} = '';
|
||||
$settings{'EXTIP'} = '';
|
||||
$settings{'PORT'} = '';
|
||||
$settings{'PROTO'} = '';
|
||||
$settings{'SEL'} = '';
|
||||
$settings{'MODE'} = '';
|
||||
$settings{'ENDPOINTS'} = '';
|
||||
$settings{'EPORT'} = '';
|
||||
$settings{'MONITOR'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb lb config entries'}, 1, '');
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
my %checked=(); # Checkbox manipulations
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
$checked{'EN'}{'on'} = ($settings{'EN'} eq '' ) ? '' : "checked='checked'";
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb add'});
|
||||
}
|
||||
|
||||
my @PROTOCOLS = ("tcp", "udp");
|
||||
my @ALGO = ("rr", "hash", "priority", "persist", "lc");
|
||||
my @MODE = ("default", "onearm", "fullnat", "dsr");
|
||||
my @MONITOR = ("on", "off");
|
||||
my @VIP;
|
||||
push(@VIP, @REDIP);
|
||||
|
||||
foreach my $line (@IPFILE) {
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
if ($temp[1] eq "red0") {
|
||||
my @tmp = split(/\//, $temp[0]);
|
||||
push(@VIP, $tmp[0]);
|
||||
}
|
||||
}
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb name'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='NAME' value='$settings{'NAME'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb extip'}: </td>
|
||||
<td>
|
||||
<select name='EXTIP' id='extip' style="width: 95px;">
|
||||
END
|
||||
|
||||
foreach (@VIP) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'EXTIP'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
<td class='base'>$Lang::tr{'enabled'}</td>
|
||||
<td><input type='checkbox' name='EN' $checked{'EN'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb port'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='PORT' value='$settings{'PORT'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb proto'}: </td>
|
||||
<td>
|
||||
<select name='PROTO' id='protocol' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@PROTOCOLS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'PROTO'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb sel'}: </td>
|
||||
<td>
|
||||
<select name='SEL' id='select' style="width: 95px;">
|
||||
END
|
||||
|
||||
foreach (@ALGO) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'SEL'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb mode'}: </td>
|
||||
<td>
|
||||
<select name='MODE' id='mode' style="width: 95px;">
|
||||
|
||||
END
|
||||
|
||||
foreach (@MODE) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'MODE'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb endpoints'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='ENDPOINTS' value='$settings{'ENDPOINTS'}' size='50'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb eport'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='EPORT' value='$settings{'EPORT'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb lb monitor'}: </td>
|
||||
<td>
|
||||
<select name='MONITOR' id='monitor' style="width: 95px;">
|
||||
|
||||
END
|
||||
|
||||
foreach (@MONITOR) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'MONITOR'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb lb config entries'});
|
||||
print <<END
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?NAME'><b>$Lang::tr{'loxilb lb name'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?EXTIP'><b>$Lang::tr{'loxilb lb extip'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?PORT'><b>$Lang::tr{'loxilb lb port'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?PROTO'><b>$Lang::tr{'loxilb lb proto'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?SEL'><b>$Lang::tr{'loxilb lb sel'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?MODE'><b>$Lang::tr{'loxilb lb mode'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ENDPOINTS'><b>$Lang::tr{'loxilb lb endpoints'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?EPORT'><b>$Lang::tr{'loxilb lb eport'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?MONITOR'><b>$Lang::tr{'loxilb lb monitor'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>$temp[2]</td>
|
||||
<td align='center' $col>$temp[3]</td>
|
||||
<td align='center' $col>$temp[4]</td>
|
||||
<td align='center' $col>$temp[5]</td>
|
||||
<td align='center' $col>$temp[6]</td>
|
||||
<td align='center' $col>$temp[7]</td>
|
||||
<td align='center' $col>$temp[8]</td>
|
||||
<td align='center' $col>$temp[9]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'edit'}' />
|
||||
<input type='image' name='$Lang::tr{'edit'}' src='/images/edit.gif' alt='$Lang::tr{'edit'}' title='$Lang::tr{'edit'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/edit.gif' alt='$Lang::tr{'edit'}' /></td>
|
||||
<td class='base'>$Lang::tr{'edit'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_NAMELIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_NAMELIST'},0,length($settings{'SORT_NAMELIST'})-3);
|
||||
if ($qs eq 'NAME') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_NAMELIST'};
|
||||
if ($qs eq 'NAME') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'EN',$temp[0],'NAME',$temp[1],'EXTIP',$temp[2],'PORT',$temp[3],'PROTO',$temp[4],'SEL',$temp[5],'MODE',$temp[6],'ENDPOINTS',$temp[7],'EPORT',$temp[8],'MONITOR',$temp[9]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$datafile") or die 'routing datafile error';
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{EN},$entries{$entry}->{NAME},$entries{$entry}->{EXTIP},$entries{$entry}->{PORT},$entries{$entry}->{PROTO},$entries{$entry}->{SEL},$entries{$entry}->{MODE},$entries{$entry}->{ENDPOINTS},$entries{$entry}->{EPORT},$entries{$entry}->{MONITOR}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$datafile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
#
|
||||
# Build the configuration file
|
||||
#
|
||||
sub CreateLB {
|
||||
my (%settings) = @_;
|
||||
my $sel;
|
||||
my $mode;
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $name = "--name=" . "$settings{'NAME'}";
|
||||
my $proto = "--" . "$settings{'PROTO'}" . "=" . "$settings{'PORT'}" . ":" . "$settings{'EPORT'}";
|
||||
|
||||
if ($settings{'SEL'}) {
|
||||
$sel = "--select=" . "$settings{'SEL'}";
|
||||
}
|
||||
if ($settings{'MODE'}) {
|
||||
$mode = "--mode=" . "$settings{'MODE'}";
|
||||
}
|
||||
my $tmp = $settings{'ENDPOINTS'};
|
||||
$tmp =~ s/\|/,/g;
|
||||
my $endpoints = "--endpoints=$tmp";
|
||||
push(@loxicmd_options, "create", "lb");
|
||||
push(@loxicmd_options, "$settings{'EXTIP'}");
|
||||
push(@loxicmd_options, "$name");
|
||||
push(@loxicmd_options, "$proto");
|
||||
if ($sel) {
|
||||
push(@loxicmd_options, "$sel");
|
||||
}
|
||||
if ($mode) {
|
||||
push(@loxicmd_options, "$mode");
|
||||
}
|
||||
push(@loxicmd_options, "$endpoints");
|
||||
if ($settings{'MONITOR'} eq 'on') {
|
||||
push(@loxicmd_options, "--monitor");
|
||||
}
|
||||
&General::system($command, @loxicmd_options);
|
||||
}
|
||||
|
||||
sub DeleteLB {
|
||||
my (%settings) = @_;
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $name = "--name=" . "$settings{'NAME'}";
|
||||
push(@loxicmd_options, "delete", "lb");
|
||||
push(@loxicmd_options, "$name");
|
||||
&General::system($command, @loxicmd_options);
|
||||
}
|
||||
642
html/cgi-bin/loxilbfw.cgi
Normal file
@@ -0,0 +1,642 @@
|
||||
#!/usr/bin/perl
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2011 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire Team #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
use strict;
|
||||
|
||||
# enable only the following on debugging purpose
|
||||
use warnings;
|
||||
#use CGI::Carp 'fatalsToBrowser';
|
||||
|
||||
require '/var/ipfire/general-functions.pl';
|
||||
require "${General::swroot}/lang.pl";
|
||||
require "${General::swroot}/header.pl";
|
||||
|
||||
#workaround to suppress a warning when a variable is used only once
|
||||
my @dummy = ( ${Header::colouryellow} );
|
||||
undef (@dummy);
|
||||
|
||||
# Files used
|
||||
my $setting = "${General::swroot}/main/settings";
|
||||
our $datafile = "${General::swroot}/loxilb/fwconfig"; #(our: used in subroutine)
|
||||
|
||||
my %color = ();
|
||||
my %mainsettings = ();
|
||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||
|
||||
our %settings = ();
|
||||
|
||||
$settings{'EN'} = ''; # reuse for dummy field in position zero
|
||||
$settings{'sourceIP'} = '';
|
||||
$settings{'destinationIP'} = '';
|
||||
$settings{'minSourcePort'} = '';
|
||||
$settings{'maxSourcePort'} = '';
|
||||
$settings{'minDestinationPort'} = '';
|
||||
$settings{'maxDestinationPort'} = '';
|
||||
$settings{'protocol'} = '';
|
||||
$settings{'portName'} = '';
|
||||
$settings{'preference'} = '';
|
||||
$settings{'ruleAction'} = '';
|
||||
my @nosaved=('EN','sourceIP','destinationIP','minSourcePort','maxSourcePort','minDestinationPort','maxDestinationPort','protocol','portName','preference','ruleAction'); # List here ALL setting2 fields. Mandatory
|
||||
|
||||
$settings{'ACTION'} = ''; # add/edit/remove
|
||||
$settings{'KEY1'} = ''; # point record for ACTION
|
||||
|
||||
#Define each field that can be used to sort columns
|
||||
my $sortstring='^sourceIP';
|
||||
$settings{'SORT_sourceIPLIST'} = 'sourceIP';
|
||||
my $errormessage = '';
|
||||
my $warnmessage = '';
|
||||
|
||||
&Header::showhttpheaders();
|
||||
|
||||
#Get GUI values
|
||||
&Header::getcgihash(\%settings);
|
||||
|
||||
###############
|
||||
# DEBUG DEBUG
|
||||
#&Header::openbox('100%', 'left', 'DEBUG');
|
||||
#my $debugCount = 0;
|
||||
#foreach my $line (sort keys %settings) {
|
||||
#print "$line = $settings{$line}<br />\n";
|
||||
# $debugCount++;
|
||||
#}
|
||||
#print " Count: $debugCount\n";
|
||||
#&Header::closebox();
|
||||
# DEBUG DEBUG
|
||||
###############
|
||||
|
||||
# Load multiline data
|
||||
our @current = ();
|
||||
if (open(FILE, "$datafile")) {
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
## Settings1 Box not used...
|
||||
&General::readhash("${General::swroot}/main/settings", \%settings);
|
||||
|
||||
|
||||
## Now manipulate the multi-line list with Settings2
|
||||
# Basic actions are:
|
||||
# toggle the check box
|
||||
# add/update a new line
|
||||
# begin editing a line
|
||||
# remove a line
|
||||
|
||||
|
||||
# Toggle enable/disable field. Field is in second position
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'toggle enable disable'}) {
|
||||
#move out new line
|
||||
chomp(@current[$settings{'KEY1'}]);
|
||||
my @temp = split(/\,/,@current[$settings{'KEY1'}]);
|
||||
|
||||
$temp[0] = $temp[0] ne '' ? '' : 'on'; # Toggle the field
|
||||
@current[$settings{'KEY1'}] = join (',',@temp)."\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
|
||||
#Save current
|
||||
open(FILE, ">$datafile") or die 'loxilb fw datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
|
||||
# Rebuild configuration file
|
||||
#&BuildConfiguration;
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'add'}) {
|
||||
# Validate inputs
|
||||
if (!&General::validipandmask($settings{'sourceIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}else{
|
||||
#set networkip if not already correctly defined
|
||||
my($ip,$cidr) = split(/\//,$settings{'sourceIP'});
|
||||
$cidr = &General::iporsubtocidr($cidr);
|
||||
my $netip=&General::getnetworkip($ip,$cidr);
|
||||
$settings{'sourceIP'} = "$netip/$cidr";
|
||||
}
|
||||
|
||||
if (!&General::validipandmask($settings{'destinationIP'})){
|
||||
$errormessage = $Lang::tr{'invalid ip'}." / ".$Lang::tr{'invalid netmask'};
|
||||
}else{
|
||||
#set networkip if not already correctly defined
|
||||
my($ip,$cidr) = split(/\//,$settings{'destinationIP'});
|
||||
$cidr = &General::iporsubtocidr($cidr);
|
||||
my $netip=&General::getnetworkip($ip,$cidr);
|
||||
$settings{'destinationIP'} = "$netip/$cidr";
|
||||
}
|
||||
|
||||
#Check for already existing routing entry
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # destinationIP
|
||||
$temp[3] ='' unless defined $temp[2]; # minSourcePort
|
||||
$temp[4] ='' unless defined $temp[3]; # maxSourcePort
|
||||
$temp[5] ='' unless defined $temp[4]; # minDestinationPort
|
||||
$temp[6] ='' unless defined $temp[5]; # maxDestinationPort
|
||||
$temp[7] ='' unless defined $temp[6]; # protocol
|
||||
$temp[8] ='' unless defined $temp[7]; # portName
|
||||
$temp[9] ='' unless defined $temp[8]; # preference
|
||||
$temp[10] ='' unless defined $temp[9]; # ruleAction
|
||||
#Same ip already used?
|
||||
if($temp[1] eq $settings{'sourceIP'} && $settings{'KEY1'} eq ''){
|
||||
$errormessage = $Lang::tr{'ccd err loxilbconfigeexist'};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
unless ($errormessage) {
|
||||
if ($settings{'KEY1'} eq '') { #add or edit ?
|
||||
unshift (@current, "$settings{'EN'},$settings{'sourceIP'},$settings{'destinationIP'},$settings{'minSourcePort'},$settings{'maxSourcePort'},$settings{'minDestinationPort'},$settings{'maxDestinationPort'},$settings{'protocol'},$settings{'portName'},$settings{'preference'},$settings{'ruleAction'}\n");
|
||||
&General::log($Lang::tr{'loxilb lb config added'});
|
||||
} else {
|
||||
@current[$settings{'KEY1'}] = "$settings{'EN'},$settings{'sourceIP'},$settings{'destinationIP'},$settings{'minSourcePort'},$settings{'maxSourcePort'},$settings{'minDestinationPort'},$settings{'maxDestinationPort'},$settings{'protocol'},$settings{'portName'},$settings{'preference'},$settings{'ruleAction'}\n";
|
||||
$settings{'KEY1'} = ''; # End edit mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
}
|
||||
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&DeleteFW(%settings);
|
||||
&CreateFW(%settings);
|
||||
}
|
||||
|
||||
# Write changes to config file.
|
||||
&SortDataFile; # sort newly added/modified entry
|
||||
|
||||
#map ($settings{$_}='' ,@nosaved); # Clear fields
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'edit'}) {
|
||||
#move out new line
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'sourceIP'}=$temp[1];
|
||||
$settings{'destinationIP'}=$temp[2];
|
||||
$settings{'minSourcePort'}=$temp[3];
|
||||
$settings{'maxSourcePort'}=$temp[4];
|
||||
$settings{'minDestinationPort'}=$temp[5];
|
||||
$settings{'maxDestinationPort'}=$temp[6];
|
||||
$settings{'protocol'}=$temp[7];
|
||||
$settings{'portName'}=$temp[8];
|
||||
$settings{'preference'}=$temp[9];
|
||||
$settings{'ruleAction'}=$temp[10];
|
||||
if ($settings{'EN'} eq 'on') {
|
||||
&CreateFW(%settings);
|
||||
}
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq $Lang::tr{'remove'}) {
|
||||
|
||||
my $line = @current[$settings{'KEY1'}]; # KEY1 is the index in current
|
||||
chomp($line);
|
||||
my @temp = split(/\,/, $line);
|
||||
$settings{'EN'}=$temp[0]; # Prepare the screen for editing
|
||||
$settings{'sourceIP'}=$temp[1];
|
||||
$settings{'destinationIP'}=$temp[2];
|
||||
$settings{'minSourcePort'}=$temp[3];
|
||||
$settings{'maxSourcePort'}=$temp[4];
|
||||
$settings{'minDestinationPort'}=$temp[5];
|
||||
$settings{'maxDestinationPort'}=$temp[6];
|
||||
$settings{'protocol'}=$temp[7];
|
||||
$settings{'portName'}=$temp[8];
|
||||
$settings{'preference'}=$temp[9];
|
||||
$settings{'ruleAction'}=$temp[10];
|
||||
|
||||
&DeleteFW(%settings);
|
||||
|
||||
splice (@current,$settings{'KEY1'},1); # Delete line
|
||||
open(FILE, ">$datafile") or die 'route datafile error';
|
||||
print FILE @current;
|
||||
close(FILE);
|
||||
$settings{'KEY1'} = ''; # End remove mode
|
||||
&General::log($Lang::tr{'loxilb fw changed'});
|
||||
|
||||
#&BuildConfiguration; # then re-build conf which use new data
|
||||
}
|
||||
|
||||
## Check if sorting is asked
|
||||
# If same column clicked, reverse the sort.
|
||||
if ($ENV{'QUERY_STRING'} =~ /$sortstring/ ) {
|
||||
my $newsort=$ENV{'QUERY_STRING'};
|
||||
my $actual=$settings{'SORT_sourceIPLIST'};
|
||||
#Reverse actual sort ?
|
||||
if ($actual =~ $newsort) {
|
||||
my $Rev='';
|
||||
if ($actual !~ 'Rev') {
|
||||
$Rev='Rev';
|
||||
}
|
||||
$newsort.=$Rev;
|
||||
}
|
||||
$settings{'SORT_sourceIPLIST'}=$newsort;
|
||||
map (delete ($settings{$_}) ,(@nosaved,'ACTION','KEY1'));# Must never be saved
|
||||
&General::writehash($setting, \%settings);
|
||||
&SortDataFile;
|
||||
$settings{'ACTION'} = 'SORT'; # Create an 'ACTION'
|
||||
map ($settings{$_} = '' ,@nosaved,'KEY1'); # and reinit vars to empty
|
||||
}
|
||||
|
||||
if ($settings{'ACTION'} eq '' ) { # First launch from GUI
|
||||
# Place here default value when nothing is initialized
|
||||
$settings{'EN'} = 'on';
|
||||
$settings{'sourceIP'} = '';
|
||||
$settings{'destinationIP'} = '';
|
||||
$settings{'minSourcePort'} = '';
|
||||
$settings{'maxSourcePort'} = '';
|
||||
$settings{'minDestinationPort'} = '';
|
||||
$settings{'maxDestinationPort'} = '';
|
||||
$settings{'protocol'} = '';
|
||||
$settings{'portName'} = '';
|
||||
$settings{'preference'} = '';
|
||||
$settings{'ruleAction'} = '';
|
||||
}
|
||||
|
||||
&Header::openpage($Lang::tr{'loxilb fw entries'}, 1, '');
|
||||
&Header::openbigbox('100%', 'left', '', $errormessage);
|
||||
my %checked=(); # Checkbox manipulations
|
||||
|
||||
if ($errormessage) {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'error messages'});
|
||||
print "<font class='base' color=red>$errormessage </font>";
|
||||
&Header::closebox();
|
||||
}
|
||||
|
||||
#
|
||||
|
||||
$checked{'EN'}{'on'} = ($settings{'EN'} eq '' ) ? '' : "checked='checked'";
|
||||
|
||||
my $buttontext = $Lang::tr{'add'};
|
||||
if ($settings{'KEY1'} ne '') {
|
||||
$buttontext = $Lang::tr{'update'};
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw edit'});
|
||||
} else {
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw add'});
|
||||
}
|
||||
|
||||
my @PROTOCOLS = ("any", "tcp", "udp", "icmp");
|
||||
my @RULEACTIONS = ("allow", "drop");
|
||||
|
||||
#Edited line number (KEY1) passed until cleared by 'save' or 'remove' or 'new sort order'
|
||||
print <<END;
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='KEY1' value='$settings{'KEY1'}' />
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw sourceIP'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='sourceIP' value='$settings{'sourceIP'}' size='25'/></td>
|
||||
</tr><tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw destinationIP'} <img src='/blob.gif' alt='*' /></td>
|
||||
<td><input type='text' name='destinationIP' value='$settings{'destinationIP'}' size='25'/></td>
|
||||
<td class='base'>$Lang::tr{'enabled'}</td>
|
||||
<td><input type='checkbox' name='EN' $checked{'EN'}{'on'} /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw minSourcePort'}: </td>
|
||||
<td><input type='text' name='minSourcePort' value='$settings{'minSourcePort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw maxSourcePort'}: </td>
|
||||
<td><input type='text' name='maxSourcePort' value='$settings{'maxSourcePort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw minDestinationPort'}: </td>
|
||||
<td><input type='text' name='minDestinationPort' value='$settings{'minDestinationPort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw maxDestinationPort'}: </td>
|
||||
<td><input type='text' name='maxDestinationPort' value='$settings{'maxDestinationPort'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw proto'}: </td>
|
||||
<td>
|
||||
<select name='protocol' id='protocol' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@PROTOCOLS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'protocol'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw portName'}: </td>
|
||||
<td><input type='text' name='portName' value='$settings{'portName'}' size='25'/></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw preference'}: </td>
|
||||
<td><input type='text' name='preference' value='$settings{'preference'}' size='25'/></td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class='base'>$Lang::tr{'loxilb fw action'}: </td>
|
||||
<td>
|
||||
<select name='ruleAction' id='ruleAction' style="width: 95px;">
|
||||
END
|
||||
|
||||
# Insert the dynamic options for the 'PROTO' select element
|
||||
foreach (@RULEACTIONS) {
|
||||
print "<option value=\"$_\"";
|
||||
if ($_ eq $settings{'ruleAction'}) {
|
||||
print " selected=\"selected\"";
|
||||
}
|
||||
print ">$_</option>";
|
||||
}
|
||||
|
||||
print <<END;
|
||||
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
<br>
|
||||
<table width='100%'>
|
||||
<tr>
|
||||
<td class='base' width='25%'><img src='/blob.gif' align='top' alt='*' /> $Lang::tr{'required field'}</td>
|
||||
<td width='50%' align='right'><input type='hidden' name='ACTION' value='$Lang::tr{'add'}' /><input type='submit' name='SUBMIT' value='$buttontext' /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
END
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::openbox('100%', 'left', $Lang::tr{'loxilb fw entries'});
|
||||
print <<END
|
||||
|
||||
<table width='100%' class='tbl'>
|
||||
<tr>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?sourceIP'><b>$Lang::tr{'loxilb fw sourceIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?destinationIP'><b>$Lang::tr{'loxilb fw destinationIP'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?minSourcePort'><b>$Lang::tr{'loxilb fw minSourcePort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?maxSourcePort'><b>$Lang::tr{'loxilb fw maxSourcePort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?minDestinationPort'><b>$Lang::tr{'loxilb fw minDestinationPort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?maxDestinationPort'><b>$Lang::tr{'loxilb fw maxDestinationPort'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?protocol'><b>$Lang::tr{'loxilb fw proto'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?portName'><b>$Lang::tr{'loxilb fw portName'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?preference'><b>$Lang::tr{'loxilb fw preference'}</b></a></th>
|
||||
<th width='10%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ruleAction'><b>$Lang::tr{'loxilb fw action'}</b></a></th>
|
||||
<th width='10%' colspan='3' class='boldbase' align='center'><b>$Lang::tr{'action'}</b></th>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
|
||||
#
|
||||
# Print each line of @current list
|
||||
#
|
||||
|
||||
my $key = 0;
|
||||
my $col="";
|
||||
foreach my $line (@current) {
|
||||
chomp($line); # remove newline
|
||||
my @temp=split(/\,/,$line);
|
||||
$temp[2] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[3] ='' unless defined $temp[2]; # not always populated
|
||||
$temp[4] ='' unless defined $temp[3]; # not always populated
|
||||
$temp[5] ='' unless defined $temp[4]; # not always populated
|
||||
$temp[6] ='' unless defined $temp[5]; # not always populated
|
||||
$temp[7] ='' unless defined $temp[6]; # not always populated
|
||||
$temp[8] ='' unless defined $temp[7]; # not always populated
|
||||
$temp[9] ='' unless defined $temp[8]; # not always populated
|
||||
$temp[10] ='' unless defined $temp[9]; # not always populated
|
||||
|
||||
#Choose icon for checkbox
|
||||
my $gif = '';
|
||||
my $gdesc = '';
|
||||
if ($temp[0] ne '' ) {
|
||||
$gif = 'on.gif';
|
||||
$gdesc = $Lang::tr{'click to disable'};
|
||||
} else {
|
||||
$gif = 'off.gif';
|
||||
$gdesc = $Lang::tr{'click to enable'};
|
||||
}
|
||||
|
||||
#Colorize each line
|
||||
if ($settings{'KEY1'} eq $key) {
|
||||
print "<tr bgcolor='${Header::colouryellow}'>";
|
||||
} elsif ($key % 2) {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color20'}'";
|
||||
} else {
|
||||
print "<tr>";
|
||||
$col="bgcolor='$color{'color22'}'";
|
||||
}
|
||||
print <<END
|
||||
<td align='center' $col>$temp[1]</td>
|
||||
<td align='center' $col>$temp[2]</td>
|
||||
<td align='center' $col>$temp[3]</td>
|
||||
<td align='center' $col>$temp[4]</td>
|
||||
<td align='center' $col>$temp[5]</td>
|
||||
<td align='center' $col>$temp[6]</td>
|
||||
<td align='center' $col>$temp[7]</td>
|
||||
<td align='center' $col>$temp[8]</td>
|
||||
<td align='center' $col>$temp[9]</td>
|
||||
<td align='center' $col>$temp[10]</td>
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'toggle enable disable'}' />
|
||||
<input type='image' name='$Lang::tr{'toggle enable disable'}' src='/images/$gif' alt='$gdesc' title='$gdesc' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
|
||||
<td align='center' $col>
|
||||
<form method='post' action='$ENV{'SCRIPT_NAME'}'>
|
||||
<input type='hidden' name='ACTION' value='$Lang::tr{'remove'}' />
|
||||
<input type='image' name='$Lang::tr{'remove'}' src='/images/delete.gif' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' />
|
||||
<input type='hidden' name='KEY1' value='$key' />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
END
|
||||
;
|
||||
$key++;
|
||||
}
|
||||
print "</table>";
|
||||
|
||||
# If table contains entries, print 'Key to action icons'
|
||||
if ($key) {
|
||||
print <<END
|
||||
<table>
|
||||
<tr>
|
||||
<td class='boldbase'> <b>$Lang::tr{'legend'}: </b></td>
|
||||
<td><img src='/images/on.gif' alt='$Lang::tr{'click to disable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to disable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/off.gif' alt='$Lang::tr{'click to enable'}' /></td>
|
||||
<td class='base'>$Lang::tr{'click to enable'}</td>
|
||||
<td> </td>
|
||||
<td><img src='/images/delete.gif' alt='$Lang::tr{'remove'}' /></td>
|
||||
<td class='base'>$Lang::tr{'remove'}</td>
|
||||
</tr>
|
||||
</table>
|
||||
END
|
||||
;
|
||||
}
|
||||
|
||||
&Header::closebox();
|
||||
|
||||
&Header::closebigbox();
|
||||
&Header::closepage();
|
||||
|
||||
## Ouf it's the end !
|
||||
|
||||
# Sort the "current" array according to choices
|
||||
sub SortDataFile
|
||||
{
|
||||
our %entries = ();
|
||||
|
||||
# Sort pair of record received in $a $b special vars.
|
||||
# When IP is specified use numeric sort else alpha.
|
||||
# If sortname ends with 'Rev', do reverse sort.
|
||||
#
|
||||
sub fixedleasesort {
|
||||
my $qs=''; # The sort field specified minus 'Rev'
|
||||
if (rindex ($settings{'SORT_sourceIPLIST'},'Rev') != -1) {
|
||||
$qs=substr ($settings{'SORT_sourceIPLIST'},0,length($settings{'SORT_sourceIPLIST'})-3);
|
||||
if ($qs eq 'sourceIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($b[0]<=>$a[0]) ||
|
||||
($b[1]<=>$a[1]) ||
|
||||
($b[2]<=>$a[2]) ||
|
||||
($b[3]<=>$a[3]);
|
||||
} else {
|
||||
$entries{$b}->{$qs} cmp $entries{$a}->{$qs};
|
||||
}
|
||||
} else { #not reverse
|
||||
$qs=$settings{'SORT_sourceIPLIST'};
|
||||
if ($qs eq 'sourceIP') {
|
||||
my @a = split(/\./,$entries{$a}->{$qs});
|
||||
my @b = split(/\./,$entries{$b}->{$qs});
|
||||
($a[0]<=>$b[0]) ||
|
||||
($a[1]<=>$b[1]) ||
|
||||
($a[2]<=>$b[2]) ||
|
||||
($a[3]<=>$b[3]);
|
||||
} else {
|
||||
$entries{$a}->{$qs} cmp $entries{$b}->{$qs};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Use an associative array (%entries)
|
||||
my $key = 0;
|
||||
foreach my $line (@current) {
|
||||
chomp( $line); #remove newline because can be on field 5 or 6 (addition of REMARK)
|
||||
my @temp = ( '','','', '');
|
||||
@temp = split (',',$line);
|
||||
|
||||
# Build a pair 'Field Name',value for each of the data dataline.
|
||||
# Each SORTABLE field must have is pair.
|
||||
# Other data fields (non sortable) can be grouped in one
|
||||
|
||||
my @record = ('KEY',$key++,'EN',$temp[0],'sourceIP',$temp[1],'destinationIP',$temp[2],'minSourcePort',$temp[3],'maxSourcePort',$temp[4],'minDestinationPort',$temp[5],'maxDestinationPort',$temp[6],'protocol',$temp[7],'portName',$temp[8],'preference',$temp[9],'ruleAction',$temp[10]);
|
||||
my $record = {}; # create a reference to empty hash
|
||||
%{$record} = @record; # populate that hash with @record
|
||||
$entries{$record->{KEY}} = $record; # add this to a hash of hashes
|
||||
}
|
||||
|
||||
open(FILE, ">$datafile") or die 'routing datafile error';
|
||||
|
||||
# Each field value is printed , with the newline ! Don't forget separator and order of them.
|
||||
foreach my $entry (sort fixedleasesort keys %entries) {
|
||||
print FILE "$entries{$entry}->{EN},$entries{$entry}->{sourceIP},$entries{$entry}->{destinationIP},$entries{$entry}->{minSourcePort},$entries{$entry}->{maxSourcePort},$entries{$entry}->{minDestinationPort},$entries{$entry}->{maxDestinationPort},$entries{$entry}->{protocol},$entries{$entry}->{portName},$entries{$entry}->{preference},$entries{$entry}->{ruleAction}\n";
|
||||
}
|
||||
|
||||
close(FILE);
|
||||
# Reload sorted @current
|
||||
open (FILE, "$datafile");
|
||||
@current = <FILE>;
|
||||
close (FILE);
|
||||
}
|
||||
|
||||
sub manageFW {
|
||||
my ($action, %settings) = @_;
|
||||
|
||||
# Initialize variables
|
||||
my @loxicmd_options;
|
||||
my $command = 'loxicmd';
|
||||
my $firewallRule = "--firewallRule="; # Start quote
|
||||
|
||||
# Construct firewall rule
|
||||
$firewallRule .= "sourceIP:$settings{'sourceIP'},destinationIP:$settings{'destinationIP'}";
|
||||
$firewallRule .= ",minSourcePort:$settings{'minSourcePort'}" if $settings{'minSourcePort'};
|
||||
$firewallRule .= ",maxSourcePort:$settings{'maxSourcePort'}" if $settings{'maxSourcePort'};
|
||||
$firewallRule .= ",minDestinationPort:$settings{'minDestinationPort'}" if $settings{'minDestinationPort'};
|
||||
$firewallRule .= ",maxDestinationPort:$settings{'maxDestinationPort'}" if $settings{'maxDestinationPort'};
|
||||
$firewallRule .= ",portName:$settings{'portName'}" if $settings{'portName'};
|
||||
|
||||
if ($settings{'protocol'} eq "any") {
|
||||
$firewallRule .= ",protocol:0";
|
||||
} elsif ($settings{'protocol'} eq "tcp") {
|
||||
$firewallRule .= ",protocol:6";
|
||||
} elsif ($settings{'protocol'} eq "udp") {
|
||||
$firewallRule .= ",protocol:17";
|
||||
} elsif ($settings{'protocol'} eq "icmp") {
|
||||
$firewallRule .= ",protocol:1";
|
||||
}
|
||||
|
||||
$firewallRule .= ",preference:$settings{'preference'}" if $settings{'preference'};
|
||||
|
||||
my $ruleAction = "--$settings{'ruleAction'}";
|
||||
|
||||
# Push options for loxicmd
|
||||
if ($action eq "create") {
|
||||
push(@loxicmd_options, $action, "firewall", $firewallRule, $ruleAction);
|
||||
} else {
|
||||
push(@loxicmd_options, $action, "firewall", $firewallRule);
|
||||
}
|
||||
|
||||
# Execute the command
|
||||
my $result = &General::system($command, @loxicmd_options);
|
||||
|
||||
# Check for errors
|
||||
if ($result != 0) {
|
||||
print "Error: Failed to execute loxicmd command.\n";
|
||||
# You might want to add more detailed error handling here
|
||||
}
|
||||
}
|
||||
|
||||
sub CreateFW {
|
||||
my (%settings) = @_;
|
||||
manageFW("create", %settings);
|
||||
}
|
||||
|
||||
sub DeleteFW {
|
||||
my (%settings) = @_;
|
||||
manageFW("delete", %settings);
|
||||
}
|
||||
|
||||
@@ -82,21 +82,21 @@ if ( (($remotesettings{'ACTION'} eq $Lang::tr{'save'}) || ($remotesettings{'ACTI
|
||||
&General::log("SSH Port 222");
|
||||
}
|
||||
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} || $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ){
|
||||
if ($remotesettings{'ENABLE_SSH'} eq 'off')
|
||||
{
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} || $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ){
|
||||
if ($remotesettings{'ENABLE_SSH'} eq 'off')
|
||||
{
|
||||
&General::system('/usr/bin/touch', "${General::swroot}/remote/enablessh");
|
||||
&General::system('/usr/local/bin/sshctrl');
|
||||
}
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} ) { $counter = 900;}
|
||||
elsif ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ) { $counter = 1800;}
|
||||
}
|
||||
if ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart15'} ) { $counter = 900;}
|
||||
elsif ( $remotesettings{'ACTION'} eq $Lang::tr{'ssh tempstart30'} ) { $counter = 1800;}
|
||||
|
||||
system("/usr/local/bin/sshctrl tempstart $counter >/dev/null");
|
||||
}
|
||||
else {
|
||||
system('/usr/local/bin/sshctrl') == 0
|
||||
system("/usr/local/bin/sshctrl tempstart $counter >/dev/null");
|
||||
}
|
||||
else {
|
||||
system('/usr/local/bin/sshctrl') == 0
|
||||
or $errormessage = "$Lang::tr{'bad return code'} " . $?/256;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&General::readhash("${General::swroot}/remote/settings", \%remotesettings);
|
||||
|
||||
@@ -142,7 +142,7 @@ print <<END
|
||||
<div id="logo">
|
||||
<h1>
|
||||
<a href="https://www.ipfire.org">
|
||||
IPFire_
|
||||
BPFire_
|
||||
</a>
|
||||
END
|
||||
;
|
||||
|
||||
BIN
images/bpfire-lb-en.png
Normal file
|
After Width: | Height: | Size: 154 KiB |
BIN
images/bpfire-lb-zh.png
Normal file
|
After Width: | Height: | Size: 176 KiB |
BIN
images/cn-1.png
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
images/cn-2.png
Normal file
|
After Width: | Height: | Size: 170 KiB |
BIN
images/en-1.png
Normal file
|
After Width: | Height: | Size: 141 KiB |
BIN
images/en-2.png
Normal file
|
After Width: | Height: | Size: 144 KiB |
BIN
images/hyperv-1.png
Normal file
|
After Width: | Height: | Size: 253 KiB |
BIN
images/hyperv-2.png
Normal file
|
After Width: | Height: | Size: 181 KiB |
@@ -141,6 +141,7 @@
|
||||
'activate' => 'Activate',
|
||||
'activate user' => 'Activate user',
|
||||
'active' => 'Active',
|
||||
'standby' => 'Standby',
|
||||
'add' => 'Add',
|
||||
'add a host' => 'Add a host',
|
||||
'add a new rule' => 'Add a new rule:',
|
||||
@@ -611,6 +612,7 @@
|
||||
'ccd err invalidnet' => 'Invalid IP address. Format: 192.168.0.0/24 or 192.168.0.0/255.255.255.0.',
|
||||
'ccd err iroute' => 'Network address for route is invalid.',
|
||||
'ccd err irouteexist' => 'This route is already in use.',
|
||||
'ccd err loxilbconfigeexist' => 'This lb is already in use.',
|
||||
'ccd err isipsecnet' => 'The given subnet address is already used by an IPsec network.',
|
||||
'ccd err isipsecrw' => 'The given subnet address is already used by the IPsec rw network.',
|
||||
'ccd err isovpnn2n' => 'The subnet address is already in use for an OpenVPN net-to-net connection.',
|
||||
@@ -703,7 +705,7 @@
|
||||
'could not retrieve common name from certificate' => 'Could not retrieve common name from certificate.',
|
||||
'count' => 'Count',
|
||||
'countries' => 'Countries',
|
||||
'country' => 'Country',
|
||||
'country' => 'Country/Region',
|
||||
'country codes and flags' => 'Country Codes and Flags:',
|
||||
'countrycode' => 'Code',
|
||||
'cpu frequency' => 'CPU frequency',
|
||||
@@ -1254,6 +1256,7 @@
|
||||
'fwdfw toggle' => 'Activate or deactivate',
|
||||
'fwdfw togglelog' => 'Activate or deactivate logging',
|
||||
'fwdfw use nat' => 'Use Network Address Translation (NAT)',
|
||||
'fwdfw use synproxy' => 'Use XDP TCP SYNPROXY acceleration:',
|
||||
'fwdfw use srcport' => 'Source port:',
|
||||
'fwdfw use srv' => 'Destination port:',
|
||||
'fwdfw useless rule' => 'This rule is useless.',
|
||||
@@ -1384,6 +1387,7 @@
|
||||
'graph per' => 'per',
|
||||
'green' => 'GREEN',
|
||||
'green interface' => 'Green Interface',
|
||||
'red interface' => 'Red Interface',
|
||||
'grouptype' => 'Grouptype:',
|
||||
'guaranteed bandwidth' => 'Guaranteed bandwidth',
|
||||
'guardian' => 'Guardian',
|
||||
@@ -1510,6 +1514,24 @@
|
||||
'intrusion detection system rules' => 'Ruleset',
|
||||
'intrusion detection system2' => 'Intrusion Prevention System',
|
||||
'intrusion prevention system' => 'Intrusion Prevention System',
|
||||
'ebpf xdp ddos' => 'eBPF XDP DDoS Protection',
|
||||
'ebpf xdp ddos system' => 'eBPF XDP DDoS Protection System',
|
||||
'xdp tcp' => 'XDP TCP',
|
||||
'xdp udp' => 'XDP UDP',
|
||||
'xdp dns' => 'XDP DNS',
|
||||
'xdp enable' => 'Enable DDoS',
|
||||
'xdp tcp port' => 'TCP Ports',
|
||||
'xdp udp port' => 'UDP Ports',
|
||||
'xdp dns ratelimit' => 'DNS Ratelimit:',
|
||||
'xdp udp ratelimit' => 'UDP Ratelimit:',
|
||||
'xdp status' => 'XDP Program Status',
|
||||
'xdp interface' => 'Interface',
|
||||
'xdp prio' => 'Prio',
|
||||
'xdp program' => 'Program name',
|
||||
'xdp mode' => 'Mode',
|
||||
'xdp id' => 'ID',
|
||||
'xdp tag' => 'Tag',
|
||||
'xdp action' => 'Chain actions',
|
||||
'invalid broadcast ip' => 'Invalid broadcast IP',
|
||||
'invalid cache size' => 'Invalid cache size.',
|
||||
'invalid characters found in pre-shared key' => 'Invalid characters found in pre-shared key.',
|
||||
@@ -1575,6 +1597,7 @@
|
||||
'invalid secondary dns' => 'Invalid secondary DNS.',
|
||||
'invalid secondary ntp' => 'Invalid Secondary NTP server address',
|
||||
'invalid start address' => 'Invalid start address.',
|
||||
'invalid router address' => 'Invalid router address.',
|
||||
'invalid time entered' => 'Invalid time entered.',
|
||||
'invalid time period' => 'Invalid time period',
|
||||
'invalid uplink speed' => 'Invalid uplink speed.',
|
||||
@@ -2429,10 +2452,61 @@
|
||||
'standard login script' => 'Standard login script',
|
||||
'start' => 'Start',
|
||||
'start address' => 'Start address:',
|
||||
'router address' => 'Router address:',
|
||||
'start ovpn server' => 'Start OpenVPN Server',
|
||||
'state or province' => 'State or Province',
|
||||
'static ip' => 'Static IP',
|
||||
'static routes' => 'Static Routes',
|
||||
'loxilb' => 'eBPF LoxiLB Load Balancer',
|
||||
'loxilb status' => 'Status',
|
||||
'loxilb server status' => 'Current LoxiLB server status:',
|
||||
'loxilb empty' => 'Field can not be empty',
|
||||
'loxilb enable' => 'Enable Load Balancer',
|
||||
'loxilb config' => 'LoxiLB Load Balancer Configuration',
|
||||
'loxilb lb config changed' => 'LoxiLB LB configuration is changed',
|
||||
'loxilb lb config added' => 'LoxiLB LB configuration is added',
|
||||
'loxilb lb config entries' => 'LoxiLB Loadbalaner configuration entries',
|
||||
'loxilb lb edit' => 'Edit existing lb entry',
|
||||
'loxilb lb add' => 'Add lb entry',
|
||||
'loxilb lb name' => 'Name',
|
||||
'loxilb lb extip' => 'EXTIP',
|
||||
'loxilb lb port' => 'PORT',
|
||||
'loxilb lb proto' => 'PROTO',
|
||||
'loxilb lb sel' => 'SEL',
|
||||
'loxilb lb mode' => 'MODE',
|
||||
'loxilb lb endpoints' => 'ENDPOINTS',
|
||||
'loxilb lb eport' => 'EPORT',
|
||||
'loxilb lb monitor' => 'MONITOR',
|
||||
'loxilb fw' => 'LoxiLB Firewall Configuration',
|
||||
'loxilb fw changed' => 'LoxiLB Firewall Changed',
|
||||
'loxilb fw entries' => 'LoxiLB Firewall Entries',
|
||||
'loxilb fw edit' => 'Edit LoxiLB Firewall',
|
||||
'loxilb fw add' => 'Add LoxiLB Firewall',
|
||||
'loxilb fw sourceIP' => 'sourceIP',
|
||||
'loxilb fw destinationIP' => 'destinationIP',
|
||||
'loxilb fw minSourcePort' => 'minSourcePort',
|
||||
'loxilb fw maxSourcePort' => 'maxSourcePort',
|
||||
'loxilb fw minDestinationPort' => 'minDestinationPort',
|
||||
'loxilb fw maxDestinationPort' => 'maxDestinationPort',
|
||||
'loxilb fw proto' => 'protocol',
|
||||
'loxilb fw portName' => 'iport',
|
||||
'loxilb fw preference' => 'preference',
|
||||
'loxilb fw action' => 'ruleAction',
|
||||
'loxilb ip entries' => 'LoxiLB Virtual IP Entries',
|
||||
'loxilb ip virtualIP' => 'Virtual IP',
|
||||
'loxilb ip interface' => 'Interface',
|
||||
'loxilb ip add' => 'Add Virtual IP',
|
||||
'keepalived' => 'High Availability',
|
||||
'keepalived config' => 'Keepalived Configuration',
|
||||
'keepalived status' => 'Keepalived Status',
|
||||
'keepalived state' => 'State',
|
||||
'keepalived virtual router id' => 'Virtual Router ID',
|
||||
'keepalived priority' => 'Priority',
|
||||
'keepalived advert int' => 'Advert Interval',
|
||||
'keepalived garp master delay' => 'Garp Master Delay',
|
||||
'keepalived auth pass' => 'Auth Pass',
|
||||
'keepalived unicast peer' => 'Unicast Peer',
|
||||
'keepalived virtual address' => 'Virtual Address',
|
||||
'status' => 'Status',
|
||||
'status information' => 'Status information',
|
||||
'status ovpn' => 'OpenVPN',
|
||||
|
||||
3121
langs/hk/cgi-bin/hk.pl
Normal file
@@ -7,3 +7,6 @@ ru:Русский:Russian
|
||||
nl:Nederlands:Dutch
|
||||
tr:Türkçe:Turkish
|
||||
it:Italiano:Italian
|
||||
zh:简体中文:Chinese
|
||||
hk:繁體中文:中國-香港
|
||||
tw:繁體中文:中國-台灣
|
||||
|
||||
3121
langs/tw/cgi-bin/tw.pl
Normal file
3192
langs/zh/cgi-bin/zh.pl
Normal file
79
lfs/bpftool
Normal file
@@ -0,0 +1,79 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 FireBeeOS #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 7.3.0
|
||||
|
||||
THISAPP = bpftool-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = a9414c92809875c7fa0bd4e38850f5d52ff83cef888b402b49948ea712e192b04e7af7a42da9c0e8bbd53fc7a4bb3cd00ad594dec6f1f3252f6a5cb847697150
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP)/src && sed -i -e 's/^prefix ?= \/usr\/local/prefix ?= \/usr/' Makefile
|
||||
cd $(DIR_APP)/src && make $(MAKETUNING)
|
||||
cd $(DIR_APP)/src && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
@@ -54,7 +54,7 @@ $(TARGET) :
|
||||
ethernet extrahd/bin fwlogs fwhosts firewall ipblocklist key langs logging mac main \
|
||||
menu.d modem optionsfw \
|
||||
ovpn patches pakfire portfw ppp private proxy/advanced/cre \
|
||||
proxy/calamaris/bin qos/bin red remote sensors suricata time \
|
||||
proxy/calamaris/bin qos/bin red remote ddos loxilb keepalived sensors suricata time \
|
||||
updatexlrator/bin updatexlrator/autocheck urlfilter/autoupdate urlfilter/bin vpn \
|
||||
wakeonlan wireless ; do \
|
||||
mkdir -p $(CONFIG_ROOT)/$$i; \
|
||||
@@ -68,7 +68,7 @@ $(TARGET) :
|
||||
fwhosts/customnetworks fwhosts/customhosts fwhosts/customgroups fwhosts/customservicegrp fwhosts/customlocationgrp fwlogs/ipsettings fwlogs/portsettings ipblocklist/modified \
|
||||
ipblocklist/settings mac/settings main/hosts main/routing main/security main/settings optionsfw/settings \
|
||||
ovpn/ccd.conf ovpn/ccdroute ovpn/ccdroute2 pakfire/settings portfw/config ppp/settings-1 ppp/settings-2 ppp/settings-3 ppp/settings-4 \
|
||||
ppp/settings-5 ppp/settings proxy/settings proxy/squid.conf proxy/advanced/settings proxy/advanced/cre/enable remote/settings qos/settings qos/classes qos/subclasses qos/level7config qos/portconfig \
|
||||
ppp/settings-5 ppp/settings proxy/settings proxy/squid.conf proxy/advanced/settings proxy/advanced/cre/enable remote/settings ddos/settings ddos/tcp_ports ddos/udp-ddos-settings ddos/udp_ports ddos/dns-ddos-settings loxilb/settings keepalived/keepalived.conf keepalived/runsettings keepalived/settings keepalived/configvs keepalived/configrs qos/settings qos/classes qos/subclasses qos/level7config qos/portconfig \
|
||||
qos/tosconfig suricata/settings vpn/config vpn/settings vpn/ipsec.conf \
|
||||
vpn/ipsec.secrets vpn/caconfig wakeonlan/clients.conf wireless/config wireless/settings; do \
|
||||
touch $(CONFIG_ROOT)/$$i; \
|
||||
@@ -98,6 +98,13 @@ $(TARGET) :
|
||||
cp $(DIR_SRC)/config/cfgroot/main-settings $(CONFIG_ROOT)/main/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/manualpages $(CONFIG_ROOT)/main/
|
||||
cp $(DIR_SRC)/config/cfgroot/ssh-settings $(CONFIG_ROOT)/remote/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/ddos-settings $(CONFIG_ROOT)/ddos/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/tcp_ports $(CONFIG_ROOT)/ddos/tcp_ports
|
||||
cp $(DIR_SRC)/config/cfgroot/udp-ddos-settings $(CONFIG_ROOT)/ddos/udp-ddos-settings
|
||||
cp $(DIR_SRC)/config/cfgroot/udp_ports $(CONFIG_ROOT)/ddos/udp_ports
|
||||
cp $(DIR_SRC)/config/cfgroot/dns-ddos-settings $(CONFIG_ROOT)/ddos/dns-ddos-settings
|
||||
cp $(DIR_SRC)/config/cfgroot/loxilb-settings $(CONFIG_ROOT)/loxilb/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/loxilb-FWconfig.txt $(CONFIG_ROOT)/loxilb/FWconfig.txt
|
||||
cp $(DIR_SRC)/config/cfgroot/time-settings $(CONFIG_ROOT)/time/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/logging-settings $(CONFIG_ROOT)/logging/settings
|
||||
cp $(DIR_SRC)/config/cfgroot/ethernet-vlans $(CONFIG_ROOT)/ethernet/vlans
|
||||
|
||||
@@ -39,6 +39,7 @@ PART_ROOT = /dev/mapper/$(patsubst /dev/%,%,$(DEVICE))p3
|
||||
IMAGE_FILE = /install/images/$(SNAME)-$(VERSION)-core$(CORE)-$(BUILD_ARCH).img.xz
|
||||
|
||||
FSTAB_FMT = UUID=%s %-8s %-4s %-10s %d %d\n
|
||||
BPFFS_FMT = %s %-8s %-4s %-10s %d %d\n
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
@@ -80,7 +81,7 @@ endif
|
||||
# /boot: 512 MB - OFFSET
|
||||
# / : 1800 MB
|
||||
S_BOOT := $(shell echo $$(( 1048576 - $(S_OFFSET) )))
|
||||
S_ROOT := 3773292
|
||||
S_ROOT := 11319876
|
||||
|
||||
ifeq "$(EFI)" "1"
|
||||
S_EFI = 65536 # 32 MB
|
||||
@@ -166,6 +167,9 @@ endif
|
||||
printf "$(FSTAB_FMT)" "$$(blkid -o value -s UUID $(PART_ROOT))" "/" \
|
||||
"auto" "defaults" 1 1 >> $(MNThdd)/etc/fstab
|
||||
|
||||
printf "$(BPFFS_FMT)" "bpffs" "/sys/fs/bpf" \
|
||||
"bpf" "defaults" 0 0 >> $(MNThdd)/etc/fstab
|
||||
|
||||
ifeq "$(BOOTLOADER)" "grub"
|
||||
# backup defaults file
|
||||
cp $(MNThdd)/etc/default/grub $(MNThdd)/etc/default/grub.backup
|
||||
|
||||
4
lfs/go
@@ -24,7 +24,7 @@
|
||||
|
||||
include Config
|
||||
|
||||
VER = 1.20.4
|
||||
VER = 1.22.0
|
||||
|
||||
THISAPP = go-$(VER)
|
||||
DL_FILE = go$(VER).$(GOOS)-$(GOARCH).tar.gz
|
||||
@@ -42,7 +42,7 @@ objects = $(DL_FILE)
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
go$(VER).$(GOOS)-arm64.tar.gz_BLAKE2 = 330336e36ebc7cb8666159256ff6dce965465195db84e29467fe0ffa79b1fa1b698d8751df73bec1cd7d04b528d9d6a9cad259f6ad5036eb89212ebc3e91b686
|
||||
go$(VER).$(GOOS)-amd64.tar.gz_BLAKE2 = 38cca2ef6d5b9f2ef8c3cef6726930be790bde5ee8693a22f15cad2d96212967c52de9361c996f0a7a91f3b28de83e40a9eca3618167bb1340978daf5e104cdf
|
||||
go$(VER).$(GOOS)-amd64.tar.gz_BLAKE2 = 018b9dd68d12ed0f2859993b6496d95bec946031353da022eb7fff2337c6082aadabbb4f858987d854599c1c2491e7ca404a7273bde01d61a2491097b24ce1b6
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
|
||||
@@ -135,6 +135,8 @@ $(TARGET) :
|
||||
ln -sf ../init.d/imspetor /etc/rc.d/rc3.d/S99imspetor
|
||||
ln -sf ../init.d/motion /etc/rc.d/rc3.d/S99motion
|
||||
ln -sf ../init.d/vdradmin /etc/rc.d/rc3.d/S99vdradmin
|
||||
ln -sf ../init.d/loxilb /etc/rc.d/rc3.d/S100loxilb
|
||||
ln -sf ../init.d/keepalived /etc/rc.d/rc3.d/S101keepalived
|
||||
|
||||
ln -sf ../init.d/imspetor /etc/rc.d/rc6.d/K01imspetor
|
||||
ln -sf ../init.d/motion /etc/rc.d/rc6.d/K01motion
|
||||
|
||||
@@ -82,7 +82,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
|
||||
cd $(DIR_APP) && ./configure --prefix=/usr --sysconfdir=/etc \
|
||||
--with-kernel-dir=/usr
|
||||
--with-kernel-dir=/usr --with-default-config-file=/var/ipfire/keepalived/keepalived.conf
|
||||
cd $(DIR_APP) && make $(MAKETUNING)
|
||||
cd $(DIR_APP) && make install
|
||||
|
||||
|
||||
77
lfs/libbpf
Normal file
@@ -0,0 +1,77 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 0.8.3
|
||||
|
||||
THISAPP = libbpf-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = abee71b4ae0d3a7d0cdf4c108091821d915d4712820dae3debe84b897e7fb84a2c763df508eb539bb74e7461ca2b6836325b7a3c08c6bc8aafe1ac4097614f31
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP)/src && make $(MAKETUNING)
|
||||
cd $(DIR_APP)/src && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
78
lfs/libbsd
Normal file
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2024 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 0.12.2
|
||||
|
||||
THISAPP = libbsd-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.xz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = 23a7ebce8e9426be9fc21f90fb957925095d8a4d244434ea07347c9fba4931485c8bb0b20ea84ab7da718d7ceba3bcca20a96f365063813309b82bd351ab223e
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
|
||||
cd $(DIR_APP) && ./configure --prefix=/usr
|
||||
cd $(DIR_APP) && make $(MAKETUNING)
|
||||
cd $(DIR_APP) && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
78
lfs/libmd
Normal file
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2024 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 1.1.0
|
||||
|
||||
THISAPP = libmd-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.xz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = a4dc72be4a46609d41453b19ba3110043e74fd0810d59f872e11151dbe87b0bdab203ef72c9d19255db32493b229bc0d33549e787979a42db08c838a810e1cdc
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar axf $(DIR_DL)/$(DL_FILE)
|
||||
cd $(DIR_APP) && ./configure --prefix=/usr
|
||||
cd $(DIR_APP) && make $(MAKETUNING)
|
||||
cd $(DIR_APP) && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
11
lfs/linux
@@ -157,7 +157,9 @@ else
|
||||
|
||||
# Cleanup kernel source
|
||||
cp $(DIR_SRC)/config/kernel/kernel.config.$(BUILD_ARCH)-$(VERSUFIX) $(DIR_APP)/.config
|
||||
cp $(DIR_SRC)/config/kernel/kernel.config.bpf $(DIR_APP)/bpf-config
|
||||
cd $(DIR_APP) && make oldconfig
|
||||
cd $(DIR_APP) && ./scripts/kconfig/merge_config.sh .config bpf-config
|
||||
cd $(DIR_APP) && make clean
|
||||
cd $(DIR_APP) && sed -i -e 's/EXTRAVERSION\ =.*/EXTRAVERSION\ =\ -$(VERSUFIX)/' Makefile
|
||||
|
||||
@@ -170,11 +172,18 @@ else
|
||||
# Build the kernel
|
||||
cd $(DIR_APP) && make $(MAKETUNING) $(KERNEL_TARGET) modules
|
||||
|
||||
# Build bpftool
|
||||
cd $(DIR_APP)/tools/bpf/bpftool && sed -i -e 's/^prefix ?= \/usr\/local/prefix ?= \/usr/' Makefile
|
||||
cd $(DIR_APP)/tools/bpf/bpftool && make $(MAKETUNING)
|
||||
|
||||
# Install the kernel
|
||||
cd $(DIR_APP) && cp -v arch/$(KERNEL_ARCH)/boot/$(KERNEL_TARGET) /boot/vmlinuz-$(VER)-$(VERSUFIX)
|
||||
cd $(DIR_APP) && cp -v System.map /boot/System.map-$(VER)-$(VERSUFIX)
|
||||
cd $(DIR_APP) && cp -v .config /boot/config-$(VER)-$(VERSUFIX)
|
||||
cd $(DIR_APP) && make $(MAKETUNING) modules_install
|
||||
cd $(DIR_APP) && INSTALL_MOD_STRIP=1 make $(MAKETUNING) modules_install
|
||||
|
||||
# Install bpftool
|
||||
cd $(DIR_APP)/tools/bpf/bpftool && make install
|
||||
|
||||
ifneq "$(BUILD_PLATFORM)" "x86"
|
||||
cd $(DIR_APP) && make $(MAKETUNING) dtbs
|
||||
|
||||
85
lfs/llvm-project
Normal file
@@ -0,0 +1,85 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 17.0.6
|
||||
|
||||
THISAPP = llvm-project-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = 779a428c86b5e797a1f2264e33268d69799cf7d9eb9776c38af5efca2b5b6f94248bb48409306fbd61f0d4775ee7ada3cac5490b0bd55d8f56133af1df814b07
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP)/llvm && mkdir build
|
||||
cd $(DIR_APP)/llvm/build && cmake .. -G "Ninja" -DLLVM_TARGETS_TO_BUILD="BPF;X86" \
|
||||
-DLLVM_ENABLE_PROJECTS="clang" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DLLVM_BUILD_RUNTIME=OFF \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr
|
||||
|
||||
cd $(DIR_APP)/llvm/build && ninja
|
||||
cd $(DIR_APP)/llvm/build && ninja install
|
||||
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
78
lfs/loxicmd
Normal file
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2024 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 0.9.5
|
||||
|
||||
THISAPP = loxicmd-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = 76e9315ddd791a1bbaf4cd2fbf5a646e93eca3963f46a78efe21d93a31906d01cf318e0aa930d3b4623eec786d83b4a6c7860ee21d65e5f66eb274e107b363b9
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP) && make
|
||||
cd $(DIR_APP) && cp -f loxicmd /usr/bin/loxicmd
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
82
lfs/loxilb
Normal file
@@ -0,0 +1,82 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2024 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 0.9.5
|
||||
|
||||
THISAPP = loxilb-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = b1c6b3d25543b5a4c1516e1dc35dbe393c1bd10d8b83307a857713e8ee3553690ce64ffb9d611452c68745564afc775363c90d96b53607902afe24a7d72bdcf7
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
@rm -rf /opt/loxilb
|
||||
|
||||
cd $(DIR_APP) && mkdir -p /opt/loxilb/dp
|
||||
cd $(DIR_APP) && make
|
||||
cd $(DIR_APP)/loxilb-ebpf/kernel && cp -f *.o /opt/loxilb/
|
||||
cd $(DIR_APP) && cp -f loxilb /usr/bin/loxilb
|
||||
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
80
lfs/loxilb-tc
Normal file
@@ -0,0 +1,80 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2024 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 5.11.0
|
||||
|
||||
THISAPP = loxilb-tc-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = 07ff73f6ee40ad8f4d8e74fcd42dc9adf5b1b6ed145ff0c505524913f6362d6a39510c30f9b22b2e8c7ed9a0e14875b2417068edb379c2af1feb9639edd0dd11
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
cd $(DIR_APP)/libbpf/src/ && mkdir build && DESTDIR=build OBJDIR=build make install
|
||||
cd $(DIR_APP) && export PKG_CONFIG_PATH=$(DIR_APP)/libbpf/src/ && \
|
||||
LIBBPF_FORCE=on LIBBPF_DIR=$(DIR_APP)/libbpf/src/build ./configure --prefix=/usr
|
||||
cd $(DIR_APP) && make $(MAKETUNING)
|
||||
cd $(DIR_APP) && cp -f tc/tc /usr/bin/ntc
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
include Config
|
||||
|
||||
VER = 9.6p1
|
||||
VER = 9.8p1
|
||||
|
||||
THISAPP = openssh-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
@@ -40,7 +40,7 @@ objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = dd7f6747fe89f7b386be4faaf7fc43398a9bf439e45608ae61c2126cf8743c64ef7b5af45c75e9007b0bda525f8809261ca0f2fc47ce60177ba769a5324719dd
|
||||
$(DL_FILE)_BLAKE2 = 3bf983c4ef5358054ed0104cd51d3e0069fbc2b80d8522d0df644d5508ec1d26a67bf061b1b5698d1cdf0d2cbba16b4cdca12a4ce30da24429094576a075e192
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
|
||||
78
lfs/pahole
Normal file
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 1.25
|
||||
|
||||
THISAPP = pahole-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = dc608dc6b689b3f243cd7349b83e4d6f7b641f99c8c182920a05c4fec396390ae3d3349d65d50724d1c9ee1eab2748b2d6fb05f59231f28c538c9a545ae63c09
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP) && mkdir build
|
||||
cd $(DIR_APP)/build && cmake -D__LIB=lib -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2" ..
|
||||
cd $(DIR_APP)/build && make && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
1
lfs/vim
@@ -83,6 +83,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
ln -svf vim /usr/bin/vi
|
||||
install -m 644 $(DIR_SRC)/config/vim/vimrc /etc/vimrc
|
||||
install -m 644 $(DIR_SRC)/config/vim/.vimrc /root/.vimrc
|
||||
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
|
||||
@@ -68,7 +68,7 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
done
|
||||
chown -R root:root /srv/web/ipfire
|
||||
chmod -R 755 /srv/web/ipfire/cgi-bin
|
||||
chmod -R 644 /srv/web/ipfire/html
|
||||
#chmod -R 644 /srv/web/ipfire/html
|
||||
chmod 755 /srv/web/ipfire/html /srv/web/ipfire/html/{index.cgi,redirect.cgi,images,include,themes,themes/*,themes/*/*}
|
||||
|
||||
# Reset permissions of redirect templates and theme directories
|
||||
|
||||
78
lfs/xdp-tools
Normal file
@@ -0,0 +1,78 @@
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2023 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 FireBeeOS
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
###############################################################################
|
||||
# Definitions
|
||||
###############################################################################
|
||||
|
||||
include Config
|
||||
|
||||
VER = 1.4.2
|
||||
|
||||
THISAPP = xdp-tools-$(VER)
|
||||
DL_FILE = $(THISAPP).tar.gz
|
||||
DL_FROM = $(URL_IPFIRE)
|
||||
DIR_APP = $(DIR_SRC)/$(THISAPP)
|
||||
TARGET = $(DIR_INFO)/$(THISAPP)
|
||||
|
||||
###############################################################################
|
||||
# Top-level Rules
|
||||
###############################################################################
|
||||
|
||||
objects = $(DL_FILE)
|
||||
|
||||
$(DL_FILE) = $(DL_FROM)/$(DL_FILE)
|
||||
|
||||
$(DL_FILE)_BLAKE2 = 3dbf0f1de6a1d26a816c52b14861830d607178da160cc18aafe117412a1b2db99cc1e61b4577131ec0fc6f20cefa65a2bbc60712542f1d31707a31672f73728c
|
||||
|
||||
install : $(TARGET)
|
||||
|
||||
check : $(patsubst %,$(DIR_CHK)/%,$(objects))
|
||||
|
||||
download :$(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
|
||||
b2 : $(subst %,%_BLAKE2,$(objects))
|
||||
|
||||
###############################################################################
|
||||
# Downloading, checking, b2sum
|
||||
###############################################################################
|
||||
|
||||
$(patsubst %,$(DIR_CHK)/%,$(objects)) :
|
||||
@$(CHECK)
|
||||
|
||||
$(patsubst %,$(DIR_DL)/%,$(objects)) :
|
||||
@$(LOAD)
|
||||
|
||||
$(subst %,%_BLAKE2,$(objects)) :
|
||||
@$(B2SUM)
|
||||
|
||||
###############################################################################
|
||||
# Installation Details
|
||||
###############################################################################
|
||||
|
||||
$(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects))
|
||||
@$(PREBUILD)
|
||||
@rm -rf $(DIR_APP) && cd $(DIR_SRC) && tar zxf $(DIR_DL)/$(DL_FILE)
|
||||
|
||||
cd $(DIR_APP) && sed -i -e 's/PREFIX?=\/usr\/local/PREFIX?=\/usr/' lib/defines.mk
|
||||
cd $(DIR_APP) && make && make install
|
||||
@rm -rf $(DIR_APP)
|
||||
@$(POSTBUILD)
|
||||
17
make.sh
@@ -444,10 +444,10 @@ prepareenv() {
|
||||
|
||||
if [ "${ENABLE_RAMDISK}" = "on" ]; then
|
||||
mkdir -p $BASEDIR/build/usr/src
|
||||
mount -t tmpfs tmpfs -o size=8G,nr_inodes=1M,mode=1777 $BASEDIR/build/usr/src
|
||||
mount -t tmpfs tmpfs -o size=32G,nr_inodes=1M,mode=1777 $BASEDIR/build/usr/src
|
||||
|
||||
mkdir -p ${BASEDIR}/build/tmp
|
||||
mount -t tmpfs tmpfs -o size=4G,nr_inodes=1M,mode=1777 ${BASEDIR}/build/tmp
|
||||
mount -t tmpfs tmpfs -o size=16G,nr_inodes=1M,mode=1777 ${BASEDIR}/build/tmp
|
||||
fi
|
||||
|
||||
mkdir -p $BASEDIR/build/usr/src/{cache,config,doc,html,langs,lfs,log,src,ccache}
|
||||
@@ -1681,6 +1681,11 @@ buildipfire() {
|
||||
lfsmake2 shairport-sync
|
||||
lfsmake2 borgbackup
|
||||
lfsmake2 lmdb
|
||||
lfsmake2 pahole
|
||||
lfsmake2 libbpf
|
||||
lfsmake2 bpftool
|
||||
lfsmake2 llvm-project
|
||||
lfsmake2 xdp-tools
|
||||
lfsmake2 knot
|
||||
lfsmake2 spectre-meltdown-checker
|
||||
lfsmake2 zabbix_agentd
|
||||
@@ -1711,6 +1716,12 @@ buildipfire() {
|
||||
lfsmake2 perl-URI-Encode
|
||||
lfsmake2 rsnapshot
|
||||
lfsmake2 mympd
|
||||
lfsmake2 libmd
|
||||
lfsmake2 libbsd
|
||||
lfsmake2 loxilb-tc
|
||||
lfsmake2 loxicmd
|
||||
lfsmake2 loxilb
|
||||
|
||||
|
||||
# Kernelbuild ... current we have no platform that need
|
||||
# multi kernel builds so KCFG is empty
|
||||
@@ -2031,6 +2042,7 @@ lang)
|
||||
$BASEDIR/tools/sort_strings.pl nl
|
||||
$BASEDIR/tools/sort_strings.pl tr
|
||||
$BASEDIR/tools/sort_strings.pl it
|
||||
$BASEDIR/tools/sort_strings.pl zh
|
||||
$BASEDIR/tools/check_strings.pl en > $BASEDIR/doc/language_issues.en
|
||||
$BASEDIR/tools/check_strings.pl de > $BASEDIR/doc/language_issues.de
|
||||
$BASEDIR/tools/check_strings.pl fr > $BASEDIR/doc/language_issues.fr
|
||||
@@ -2040,6 +2052,7 @@ lang)
|
||||
$BASEDIR/tools/check_strings.pl nl > $BASEDIR/doc/language_issues.nl
|
||||
$BASEDIR/tools/check_strings.pl tr > $BASEDIR/doc/language_issues.tr
|
||||
$BASEDIR/tools/check_strings.pl it > $BASEDIR/doc/language_issues.it
|
||||
$BASEDIR/tools/check_strings.pl zh > $BASEDIR/doc/language_issues.zh
|
||||
$BASEDIR/tools/check_langs.sh > $BASEDIR/doc/language_missings
|
||||
print_status DONE
|
||||
|
||||
|
||||
@@ -25515,6 +25515,7 @@ HCC 32 UK
|
||||
HCC 33 US
|
||||
HCC 34 Yugoslavia
|
||||
HCC 35 Turkish-F
|
||||
HCC 36 Chinese
|
||||
|
||||
# List of Video Class Terminal Types
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
. ${rc_functions}
|
||||
|
||||
[ -r "/etc/sysconfig/keepalive" ] && . /etc/sysconfig/keepalive
|
||||
eval $(/usr/local/bin/readhash /var/ipfire/keepalived/runsettings)
|
||||
|
||||
case "${1}" in
|
||||
start)
|
||||
@@ -32,8 +33,10 @@ case "${1}" in
|
||||
# Enable connection tracking for IPVS
|
||||
sysctl -w net.ipv4.vs.conntrack=1 &>/dev/null
|
||||
|
||||
boot_mesg "Starting keepalive daemon..."
|
||||
loadproc /usr/sbin/keepalived ${KEEPALIVED_OPTIONS}
|
||||
if [ "$ENABLE_HA" == "on" ]; then
|
||||
boot_mesg "Starting keepalive daemon..."
|
||||
loadproc /usr/sbin/keepalived ${KEEPALIVED_OPTIONS}
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
|
||||
200
src/initscripts/system/ddos
Executable file
@@ -0,0 +1,200 @@
|
||||
#!/bin/sh
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
. /etc/sysconfig/rc
|
||||
. $rc_functions
|
||||
|
||||
eval $(/usr/local/bin/readhash /var/ipfire/ddos/settings)
|
||||
eval $(/usr/local/bin/readhash /var/ipfire/ddos/udp-ddos-settings)
|
||||
eval $(/usr/local/bin/readhash /var/ipfire/ddos/dns-ddos-settings)
|
||||
|
||||
get_ports () {
|
||||
# Define an empty variable to store the output
|
||||
local output=""
|
||||
local ddos_port_file="$1"
|
||||
|
||||
# Read the input file line by line
|
||||
while IFS= read -r line; do
|
||||
# Check if the line contains '=on'
|
||||
if [[ "$line" == [0-9]*"=on" ]]; then
|
||||
# Extract the service/port number
|
||||
service=$(echo "$line" | cut -d'=' -f1)
|
||||
# Append the service/port number to the output string
|
||||
output="$output$service,"
|
||||
fi
|
||||
done < $ddos_port_file
|
||||
|
||||
# Remove the trailing comma from the output string
|
||||
output="${output%,}"
|
||||
echo $output
|
||||
}
|
||||
|
||||
load_syncookie () {
|
||||
sysctl -w net.ipv4.tcp_syncookies=2
|
||||
sysctl -w net.ipv4.tcp_timestamps=1
|
||||
sysctl -w net.netfilter.nf_conntrack_tcp_loose=0
|
||||
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
|
||||
if [ $? -eq 0 ]; then
|
||||
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
|
||||
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
|
||||
else
|
||||
xdp-loader load red0 /usr/lib/bpf/xdp_synproxy.bpf.o
|
||||
if [ $? -ge 1 ]; then
|
||||
boot_mesg "Native mode not supported, try SKB"
|
||||
xdp-loader load red0 -m skb /usr/lib/bpf/xdp_synproxy.bpf.o
|
||||
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
|
||||
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
|
||||
else
|
||||
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
|
||||
xdp_synproxy --prog $prog_id --ports="$tcp_ports"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
load_xdpudp () {
|
||||
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
|
||||
if [ $? -eq 0 ]; then
|
||||
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
|
||||
xdp-udp --prog $prog_id --ports="$udp_ports"
|
||||
else
|
||||
xdp-loader load red0 -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
|
||||
if [ $? -ge 1 ]; then
|
||||
boot_mesg "Native mode not supported, try SKB"
|
||||
xdp-loader load red0 -m skb -P 90 -p /sys/fs/bpf/xdp-udp -n xdp_udp /usr/lib/bpf/xdp_udp.bpf.o
|
||||
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
|
||||
xdp-udp --prog $prog_id --ports="$udp_ports"
|
||||
else
|
||||
prog_id=$(/usr/sbin/xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
|
||||
xdp-udp --prog $prog_id --ports="$udp_ports"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
load_xdpdns () {
|
||||
/usr/sbin/xdp-loader status red0 | grep 'xdp_dns'
|
||||
if [ $? -ne 0 ]; then
|
||||
xdp-loader load red0 -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
|
||||
if [ $? -ge 1 ]; then
|
||||
boot_mesg "Native mode not supported, try SKB"
|
||||
xdp-loader load red0 -m skb -P 80 -p /sys/fs/bpf/xdp-dns -n xdp_dns /usr/lib/bpf/xdp_dnsrrl.bpf.o
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
unload_syncookie () {
|
||||
sysctl -w net.ipv4.tcp_syncookies=1
|
||||
/usr/sbin/xdp-loader status red0 | grep 'syncookie_xdp'
|
||||
if [ $? -eq 0 ]; then
|
||||
prog_id=$(xdp-loader status red0 | grep 'syncookie_xdp' | awk '{print $4}')
|
||||
/usr/sbin/xdp-loader unload -i $prog_id red0
|
||||
else
|
||||
boot_mesg "Error syncookie_xdp not loaded!"
|
||||
fi
|
||||
}
|
||||
|
||||
unload_xdpudp () {
|
||||
/usr/sbin/xdp-loader status red0 | grep 'xdp_udp'
|
||||
if [ $? -eq 0 ]; then
|
||||
prog_id=$(xdp-loader status red0 | grep 'xdp_udp' | awk '{print $4}')
|
||||
/usr/sbin/xdp-loader unload -i $prog_id red0
|
||||
/bin/rm -rf /sys/fs/bpf/xdp-udp
|
||||
else
|
||||
boot_mesg "Error xdp_udp not loaded!"
|
||||
fi
|
||||
}
|
||||
|
||||
unload_xdpdns () {
|
||||
/usr/sbin/xdp-loader status red0 | grep 'xdp_dns'
|
||||
if [ $? -eq 0 ]; then
|
||||
prog_id=$(xdp-loader status red0 | grep 'xdp_dns' | awk '{print $4}')
|
||||
/usr/sbin/xdp-loader unload -i $prog_id red0
|
||||
/bin/rm -rf /sys/fs/bpf/xdp-dns
|
||||
else
|
||||
boot_mesg "Error xdp_dns not loaded!"
|
||||
fi
|
||||
}
|
||||
|
||||
set_ratelimit () {
|
||||
local rate=$1
|
||||
local map=$2
|
||||
hex=$(printf '%08x' "$rate") # Convert decimal to hexadecimal
|
||||
bytes=$(echo "$hex" | fold -w2 | tac) # Split the hexadecimal into pairs of bytes and reverse the order
|
||||
hex_le=$(echo "$bytes" | sed 's/^/0x/' | tr '\n' ' ') # Add prefix "0x" to each byte and concatenate them
|
||||
bpftool map update name $map key hex 00 00 00 00 value $hex_le
|
||||
}
|
||||
|
||||
tcp_ports="$(get_ports /var/ipfire/ddos/settings)"
|
||||
udp_ports="$(get_ports /var/ipfire/ddos/udp-ddos-settings)"
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ ! -e /var/ipfire/red/active ]; then
|
||||
boot_mesg " ERROR! Red0 interface not online!"
|
||||
echo_warning
|
||||
exit 1
|
||||
fi
|
||||
boot_mesg -n "Starting ddos..."
|
||||
if [ "$ENABLE_DDOS" == "on" ]; then
|
||||
load_syncookie
|
||||
fi
|
||||
if [ "$ENABLE_UDP_DDOS" == "on" ]; then
|
||||
load_xdpudp
|
||||
fi
|
||||
if [ "$ENABLE_DNS_DDOS" == "on" ]; then
|
||||
load_xdpdns
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
boot_mesg "Stopping ddos..."
|
||||
if [ "$ENABLE_DDOS" == "off" ]; then
|
||||
unload_syncookie
|
||||
fi
|
||||
if [ "$ENABLE_UDP_DDOS" == "off" ]; then
|
||||
unload_xdpudp
|
||||
if [ -n "$UDP_RATELIMIT" ]; then
|
||||
set_ratelimit $UDP_RATELIMIT "xdp_udp.data"
|
||||
fi
|
||||
fi
|
||||
if [ "$ENABLE_DNS_DDOS" == "off" ]; then
|
||||
unload_xdpdns
|
||||
if [ -n "$DNS_RATELIMIT" ]; then
|
||||
set_ratelimit $DNS_RATELIMIT "xdp_dnsr.data"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
|
||||
status)
|
||||
/usr/sbin/xdp-loader status red0
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart|status}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -70,6 +70,12 @@ iptables_init() {
|
||||
modprobe nf_log_ipv4
|
||||
sysctl -q -w net.netfilter.nf_log.2=nf_log_ipv4
|
||||
|
||||
# XDP SYNPROXY Chain, needs to be first chain in INPUT as the chain order matters
|
||||
iptables -t raw -N RAWSYNPROXY
|
||||
iptables -t raw -A PREROUTING -j RAWSYNPROXY
|
||||
iptables -N INSYNPROXY
|
||||
iptables -A INPUT -j INSYNPROXY
|
||||
|
||||
# IPS Bypass Chain which stores the BYPASS bit in connection tracking
|
||||
iptables -N IPSBYPASS
|
||||
iptables -A IPSBYPASS -j CONNMARK --save-mark --mask "$(( ~IPS_REPEAT_MASK & 0xffffffff ))"
|
||||
|
||||
71
src/initscripts/system/loxilb
Executable file
@@ -0,0 +1,71 @@
|
||||
#!/bin/sh
|
||||
###############################################################################
|
||||
# #
|
||||
# IPFire.org - A linux based firewall #
|
||||
# Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> #
|
||||
# Copyright (C) 2024 BPFire <vincent.mc.li@gmail.com> #
|
||||
# #
|
||||
# This program is free software: you can redistribute it and/or modify #
|
||||
# it under the terms of the GNU General Public License as published by #
|
||||
# the Free Software Foundation, either version 3 of the License, or #
|
||||
# (at your option) any later version. #
|
||||
# #
|
||||
# This program is distributed in the hope that it will be useful, #
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
||||
# GNU General Public License for more details. #
|
||||
# #
|
||||
# You should have received a copy of the GNU General Public License #
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
||||
# #
|
||||
###############################################################################
|
||||
|
||||
. /etc/sysconfig/rc
|
||||
. $rc_functions
|
||||
|
||||
eval $(/usr/local/bin/readhash /var/ipfire/loxilb/settings)
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
boot_mesg -n "Starting loxilb..."
|
||||
if [ "$ENABLE_LOXILB" == "on" ]; then
|
||||
if [ -d /opt/loxilb/dp/ ]; then
|
||||
umount /opt/loxilb/dp/
|
||||
rm -fr /opt/loxilb/dp/bpf
|
||||
fi
|
||||
|
||||
mkdir -p /opt/loxilb/dp/
|
||||
mount -t bpf bpf /opt/loxilb/dp/
|
||||
|
||||
#enable egress firewall SNAT for green network
|
||||
redip=$(< /var/ipfire/red/local-ipaddress)
|
||||
sed -i "s/\"REDIP\"/\"$redip\"/" /var/ipfire/loxilb/FWconfig.txt
|
||||
|
||||
loadproc -b loxilb --config-path="/var/ipfire/loxilb/" --blacklist="eth[0-9]"
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
boot_mesg "Stopping loxilb..."
|
||||
if [ "$ENABLE_LOXILB" == "off" ]; then
|
||||
#remove egress firewall SNAT for green network
|
||||
loxicmd delete firewall --firewallRule="portName:green0"
|
||||
killproc loxilb
|
||||
fi
|
||||
;;
|
||||
|
||||
status)
|
||||
statusproc /usr/bin/loxilb
|
||||
;;
|
||||
|
||||
restart)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|restart}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
@@ -46,6 +46,11 @@ case "${1}" in
|
||||
mount -t cgroup2 none /sys/fs/cgroup || failed=1
|
||||
fi
|
||||
|
||||
if ! mountpoint /sys/fs/bpf &> /dev/null; then
|
||||
boot_mesg -n " /sys/fs/bpf" ${NORMAL}
|
||||
mount -t bpf bpffs /sys/fs/bpf || failed=1
|
||||
fi
|
||||
|
||||
if ! mountpoint /sys/firmware/efi/efivars &>/dev/null && [ -d "/sys/firmware/efi" ]; then
|
||||
boot_mesg -n " /sys/firmware/efi/efivars" ${NORMAL}
|
||||
mount -t efivarfs efivarfs /sys/firmware/efi/efivars || failed=1
|
||||
|
||||
@@ -247,6 +247,7 @@ static char* center_string(const char* str, int width) {
|
||||
|
||||
#define DEFAULT_LANG "en.utf8"
|
||||
#define NUM_LANGS 13
|
||||
#define NUM_LANGS 14
|
||||
|
||||
static struct lang {
|
||||
const char* code;
|
||||
@@ -265,6 +266,7 @@ static struct lang {
|
||||
{ "pt.utf8", "Portuguese (Brasil)" },
|
||||
{ "ru.utf8", "Русский (Russian)" },
|
||||
{ "tr.utf8", "Türkçe (Turkish)" },
|
||||
{ "zh.utf8", "简体中文 (Chinese)" },
|
||||
{ NULL, NULL },
|
||||
};
|
||||
|
||||
|
||||
@@ -19,36 +19,36 @@ msgstr ""
|
||||
|
||||
#: main.c:78 main.c:179 main.c:404 main.c:670 main.c:702 main.c:893
|
||||
msgid "OK"
|
||||
msgstr ""
|
||||
msgstr "确定"
|
||||
|
||||
#: main.c:79 main.c:460 main.c:487 main.c:516 main.c:620 main.c:630 main.c:670
|
||||
#: main.c:702
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
msgstr "取消"
|
||||
|
||||
#: main.c:176
|
||||
msgid "I accept this license"
|
||||
msgstr ""
|
||||
msgstr "我接受此许可协议"
|
||||
|
||||
#: main.c:384
|
||||
msgid "Warning: Unattended installation will start in 10 seconds..."
|
||||
msgstr ""
|
||||
msgstr "警告:无人值守安装将在 10 秒钟后开始..."
|
||||
|
||||
#: main.c:403
|
||||
msgid "Language selection"
|
||||
msgstr ""
|
||||
msgstr "语言选择"
|
||||
|
||||
#: main.c:403
|
||||
msgid "Select the language you wish to use for the installation."
|
||||
msgstr ""
|
||||
msgstr "请选择安装时要使用的语言。"
|
||||
|
||||
#: main.c:418
|
||||
msgid "Unattended mode"
|
||||
msgstr ""
|
||||
msgstr "无人值守模式"
|
||||
|
||||
#: main.c:420
|
||||
msgid "<Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen"
|
||||
msgstr ""
|
||||
msgstr "<Tab>/<Alt-Tab> 切换元素 | <Space> 选择 | <F12> 下一屏幕"
|
||||
|
||||
#: main.c:426
|
||||
#, c-format
|
||||
@@ -57,15 +57,18 @@ msgid ""
|
||||
"\n"
|
||||
"Selecting Cancel on any of the following screens will reboot the computer."
|
||||
msgstr ""
|
||||
"欢迎使用 %s 安装程序。\n"
|
||||
"\n"
|
||||
"在以下任何屏幕上选择取消将重新启动计算机。"
|
||||
|
||||
#: main.c:428
|
||||
msgid "Start installation"
|
||||
msgstr ""
|
||||
msgstr "开始安装"
|
||||
|
||||
#: main.c:449
|
||||
#, c-format
|
||||
msgid "The installer will now try downloading the installation image."
|
||||
msgstr ""
|
||||
msgstr "安装程序现在将尝试下载安装镜像。"
|
||||
|
||||
#: main.c:452
|
||||
#, c-format
|
||||
@@ -74,20 +77,24 @@ msgid ""
|
||||
"\n"
|
||||
"You can try downloading the required installation image."
|
||||
msgstr ""
|
||||
"找不到源驱动器。\n"
|
||||
"\n"
|
||||
"您可以尝试下载所需的安装镜像。"
|
||||
|
||||
#: main.c:456
|
||||
msgid ""
|
||||
"Please make sure to connect your machine to a network and the installer will"
|
||||
" try connect to acquire an IP address."
|
||||
msgstr ""
|
||||
"请确保将您的机器连接到网络,安装程序将尝试连接以获取 IP 地址。"
|
||||
|
||||
#: main.c:460
|
||||
msgid "Download installation image"
|
||||
msgstr ""
|
||||
msgstr "下载安装镜像"
|
||||
|
||||
#: main.c:473
|
||||
msgid "Trying to start networking (DHCP)..."
|
||||
msgstr ""
|
||||
msgstr "正在尝试启动网络(DHCP)..."
|
||||
|
||||
#: main.c:484
|
||||
msgid ""
|
||||
@@ -95,19 +102,22 @@ msgid ""
|
||||
"\n"
|
||||
"Please connect your machine to a network with a DHCP server and retry."
|
||||
msgstr ""
|
||||
"无法启动网络,但是安装继续进行需要网络支持。\n"
|
||||
"\n"
|
||||
"请将您的机器连接到一个带有 DHCP 服务器的网络,然后重试。"
|
||||
|
||||
#: main.c:487 main.c:516
|
||||
msgid "Retry"
|
||||
msgstr ""
|
||||
msgstr "重试"
|
||||
|
||||
#: main.c:501
|
||||
msgid "Downloading installation image..."
|
||||
msgstr ""
|
||||
msgstr "正在下载安装镜像..."
|
||||
|
||||
#: main.c:510
|
||||
#, c-format
|
||||
msgid "BLAKE2 checksum mismatch"
|
||||
msgstr ""
|
||||
msgid "MD5 checksum mismatch"
|
||||
msgstr "MD5 校验和不匹配"
|
||||
|
||||
#: main.c:513
|
||||
#, c-format
|
||||
@@ -117,6 +127,10 @@ msgid ""
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"无法下载安装镜像。\n"
|
||||
" 原因:%s\n"
|
||||
"\n"
|
||||
"%s"
|
||||
|
||||
#: main.c:528
|
||||
#, c-format
|
||||
@@ -124,22 +138,24 @@ msgid ""
|
||||
"Could not mount %s to %s:\n"
|
||||
" %s\n"
|
||||
msgstr ""
|
||||
"无法挂载 %s 到 %s:\n"
|
||||
" %s\n"
|
||||
|
||||
#: main.c:543
|
||||
msgid "License Agreement"
|
||||
msgstr ""
|
||||
msgstr "许可协议"
|
||||
|
||||
#: main.c:544
|
||||
msgid "License not accepted!"
|
||||
msgstr ""
|
||||
msgstr "未接受许可协议!"
|
||||
|
||||
#: main.c:566
|
||||
msgid "No hard disk found."
|
||||
msgstr ""
|
||||
msgstr "找不到硬盘。"
|
||||
|
||||
#: main.c:587
|
||||
msgid "Disk Selection"
|
||||
msgstr ""
|
||||
msgstr "选择硬盘"
|
||||
|
||||
#: main.c:588
|
||||
msgid ""
|
||||
@@ -147,6 +163,9 @@ msgid ""
|
||||
"\n"
|
||||
"ALL DATA ON THE DISK WILL BE DESTROYED."
|
||||
msgstr ""
|
||||
"请选择要安装 IPFire 的硬盘。首先将对其进行分区,然后在分区上创建文件系统。\n"
|
||||
"\n"
|
||||
"硬盘上的所有数据将被删除。"
|
||||
|
||||
#: main.c:599
|
||||
msgid ""
|
||||
@@ -154,6 +173,9 @@ msgid ""
|
||||
"\n"
|
||||
"Please select one or more disks you want to install IPFire on."
|
||||
msgstr ""
|
||||
"未选择任何硬盘。\n"
|
||||
"\n"
|
||||
"请选择要安装 IPFire 的一个或多个硬盘。"
|
||||
|
||||
#: main.c:617
|
||||
#, c-format
|
||||
@@ -164,14 +186,19 @@ msgid ""
|
||||
"\n"
|
||||
"Do you agree to continue?"
|
||||
msgstr ""
|
||||
"安装程序将准备所选的硬盘:\n"
|
||||
"\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"您同意继续吗?"
|
||||
|
||||
#: main.c:619
|
||||
msgid "Disk Setup"
|
||||
msgstr ""
|
||||
msgstr "硬盘设置"
|
||||
|
||||
#: main.c:620 main.c:630
|
||||
msgid "Delete all data"
|
||||
msgstr ""
|
||||
msgstr "删除所有数据"
|
||||
|
||||
#: main.c:627
|
||||
#, c-format
|
||||
@@ -183,103 +210,110 @@ msgid ""
|
||||
"\n"
|
||||
"Do you agree to continue?"
|
||||
msgstr ""
|
||||
"安装程序将在选定的硬盘上设置 RAID 配置:\n"
|
||||
"\n"
|
||||
" %s\n"
|
||||
" %s\n"
|
||||
"\n"
|
||||
"您同意继续吗?"
|
||||
|
||||
#: main.c:629
|
||||
msgid "RAID Setup"
|
||||
msgstr ""
|
||||
msgstr "RAID 设置"
|
||||
|
||||
#: main.c:640
|
||||
msgid "Your disk configuration is currently not supported."
|
||||
msgstr ""
|
||||
msgstr "当前不支持您的硬盘配置。"
|
||||
|
||||
#: main.c:655
|
||||
msgid "Your harddisk is too small."
|
||||
msgstr ""
|
||||
msgstr "您的硬盘太小了。"
|
||||
|
||||
#: main.c:671
|
||||
msgid ""
|
||||
"Your harddisk is very small, but you can continue without a swap partition."
|
||||
msgstr ""
|
||||
"您的硬盘非常小,但是您可以继续安装而不创建交换分区。"
|
||||
|
||||
#: main.c:684
|
||||
msgid "ext4 Filesystem"
|
||||
msgstr ""
|
||||
msgstr "ext4 文件系统"
|
||||
|
||||
#: main.c:685
|
||||
msgid "ext4 Filesystem without journal"
|
||||
msgstr ""
|
||||
msgstr "不带日志的 ext4 文件系统"
|
||||
|
||||
#: main.c:686
|
||||
msgid "XFS Filesystem"
|
||||
msgstr ""
|
||||
msgstr "XFS 文件系统"
|
||||
|
||||
#: main.c:687
|
||||
msgid "ReiserFS Filesystem"
|
||||
msgstr ""
|
||||
msgstr "ReiserFS 文件系统"
|
||||
|
||||
#: main.c:701
|
||||
msgid "Filesystem Selection"
|
||||
msgstr ""
|
||||
msgstr "文件系统选择"
|
||||
|
||||
#: main.c:701
|
||||
msgid "Please choose your filesystem:"
|
||||
msgstr ""
|
||||
msgstr "请选择您的文件系统:"
|
||||
|
||||
#: main.c:712
|
||||
msgid "Building RAID..."
|
||||
msgstr ""
|
||||
msgstr "正在构建 RAID..."
|
||||
|
||||
#: main.c:716
|
||||
msgid "Unable to build the RAID."
|
||||
msgstr ""
|
||||
msgstr "无法构建 RAID。"
|
||||
|
||||
#: main.c:728
|
||||
msgid "Partitioning disk..."
|
||||
msgstr ""
|
||||
msgstr "正在分区硬盘..."
|
||||
|
||||
#: main.c:732
|
||||
msgid "Unable to partition the disk."
|
||||
msgstr ""
|
||||
msgstr "无法对硬盘进行分区。"
|
||||
|
||||
#: main.c:739
|
||||
msgid "Creating filesystems..."
|
||||
msgstr ""
|
||||
msgstr "正在创建文件系统..."
|
||||
|
||||
#: main.c:743
|
||||
msgid "Unable to create filesystems."
|
||||
msgstr ""
|
||||
msgstr "无法创建文件系统。"
|
||||
|
||||
#: main.c:749
|
||||
msgid "Unable to mount filesystems."
|
||||
msgstr ""
|
||||
msgstr "无法挂载文件系统。"
|
||||
|
||||
#: main.c:760
|
||||
msgid "Installing the system..."
|
||||
msgstr ""
|
||||
msgstr "正在安装系统..."
|
||||
|
||||
#: main.c:761
|
||||
msgid "Unable to install the system."
|
||||
msgstr ""
|
||||
msgstr "无法安装系统。"
|
||||
|
||||
#: main.c:777
|
||||
msgid "Installing the language cache..."
|
||||
msgstr ""
|
||||
msgstr "正在安装语言缓存..."
|
||||
|
||||
#: main.c:778
|
||||
msgid "Unable to install the language cache."
|
||||
msgstr ""
|
||||
msgstr "无法安装语言缓存。"
|
||||
|
||||
#: main.c:783
|
||||
msgid "Installing the bootloader..."
|
||||
msgstr ""
|
||||
msgstr "正在安装引导程序..."
|
||||
|
||||
#: main.c:790
|
||||
msgid "Unable to open /etc/default/grub for writing."
|
||||
msgstr ""
|
||||
msgstr "无法打开 /etc/default/grub 进行写入。"
|
||||
|
||||
#: main.c:812
|
||||
msgid "Unable to install the bootloader."
|
||||
msgstr ""
|
||||
msgstr "无法安装引导程序。"
|
||||
|
||||
#: main.c:826
|
||||
msgid ""
|
||||
@@ -287,26 +321,29 @@ msgid ""
|
||||
"\n"
|
||||
"Do you want to restore the backup?"
|
||||
msgstr ""
|
||||
"在安装映像上找到了一个备份文件。\n"
|
||||
"\n"
|
||||
"您要恢复备份吗?"
|
||||
|
||||
#: main.c:827
|
||||
msgid "Yes"
|
||||
msgstr ""
|
||||
msgstr "是"
|
||||
|
||||
#: main.c:827
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
msgstr "否"
|
||||
|
||||
#: main.c:834
|
||||
msgid "An error occured when the backup file was restored."
|
||||
msgstr ""
|
||||
msgstr "恢复备份文件时发生错误。"
|
||||
|
||||
#: main.c:869
|
||||
msgid "Running post-install script..."
|
||||
msgstr ""
|
||||
msgstr "正在运行安装后脚本..."
|
||||
|
||||
#: main.c:870
|
||||
msgid "Post-install script failed."
|
||||
msgstr ""
|
||||
msgstr "安装后脚本执行失败。"
|
||||
|
||||
#: main.c:877
|
||||
#, c-format
|
||||
@@ -315,15 +352,18 @@ msgid ""
|
||||
"\n"
|
||||
"Please remove any installation mediums from this system and hit the reboot button. Once the system has restarted you will be asked to setup networking and system passwords. After that, you should point your web browser at https://%s:444 (or what ever you name your %s) for the web configuration console."
|
||||
msgstr ""
|
||||
"%s 安装成功!\n"
|
||||
"\n"
|
||||
"请从系统中移除任何安装介质并点击重新启动按钮。系统重新启动后,您将被要求设置网络和系统密码。完成后,您可以在您命名的 %s 上通过 https://%s:444 进入 Web 配置控制台。"
|
||||
|
||||
#: main.c:882
|
||||
msgid "Congratulations!"
|
||||
msgstr ""
|
||||
msgstr "恭喜您!"
|
||||
|
||||
#: main.c:882
|
||||
msgid "Reboot"
|
||||
msgstr ""
|
||||
msgstr "重新启动"
|
||||
|
||||
#: main.c:893
|
||||
msgid "Setup has failed. Press Ok to reboot."
|
||||
msgstr ""
|
||||
msgstr "安装失败。按下“确定”重新启动。"
|
||||
|
||||
@@ -32,7 +32,7 @@ SUID_PROGS = squidctrl sshctrl ipfirereboot \
|
||||
smartctrl clamavctrl addonctrl pakfire mpfirectrl wlanapctrl \
|
||||
setaliases urlfilterctrl updxlratorctrl fireinfoctrl rebuildroutes \
|
||||
getconntracktable wirelessclient torctrl ddnsctrl unboundctrl \
|
||||
captivectrl
|
||||
captivectrl ddosctrl loxilbctrl keepalivedctrl
|
||||
|
||||
OBJS = $(patsubst %,%.o,$(PROGS) $(SUID_PROGS))
|
||||
|
||||
|
||||
40
src/misc-progs/ddosctrl.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* This file is part of the IPFire Firewall.
|
||||
*
|
||||
* This program is distributed under the terms of the GNU General Public
|
||||
* Licence. See the file COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "setuid.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (!(initsetuid()))
|
||||
exit(1);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "\nNo argument given.\n\nddosctrl (start|stop|restart)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "start") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/ddos start");
|
||||
} else if (strcmp(argv[1], "stop") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/ddos stop");
|
||||
} else if (strcmp(argv[1], "restart") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/ddos restart");
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/ddos status");
|
||||
} else {
|
||||
fprintf(stderr, "\nBad argument given.\n\nddosctrl (start|stop|restart|status)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
40
src/misc-progs/keepalivedctrl.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* This file is part of the IPFire Firewall.
|
||||
*
|
||||
* This program is distributed under the terms of the GNU General Public
|
||||
* Licence. See the file COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "setuid.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (!(initsetuid()))
|
||||
exit(1);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "\nNo argument given.\n\nkeepalivedctrl (start|stop|restart)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "start") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/keepalived start");
|
||||
} else if (strcmp(argv[1], "stop") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/keepalived stop");
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/keepalived status");
|
||||
} else if (strcmp(argv[1], "restart") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/keepalived restart");
|
||||
} else {
|
||||
fprintf(stderr, "\nBad argument given.\n\nkeepalivedctrl (start|stop|restart)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
40
src/misc-progs/loxilbctrl.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* This file is part of the IPFire Firewall.
|
||||
*
|
||||
* This program is distributed under the terms of the GNU General Public
|
||||
* Licence. See the file COPYING for details.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include "setuid.h"
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (!(initsetuid()))
|
||||
exit(1);
|
||||
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "\nNo argument given.\n\nloxilbctrl (start|stop|restart)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "start") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/loxilb start");
|
||||
} else if (strcmp(argv[1], "stop") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/loxilb stop");
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/loxilb status");
|
||||
} else if (strcmp(argv[1], "restart") == 0) {
|
||||
safe_system("/etc/rc.d/init.d/loxilb restart");
|
||||
} else {
|
||||
fprintf(stderr, "\nBad argument given.\n\nloxilbctrl (start|stop|restart)\n\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -4,6 +4,7 @@
|
||||
#
|
||||
# Translators:
|
||||
# ipfire <qiwenqiu@yahoo.com.hk>, 2015
|
||||
# bpfire <vincent.mc.li@gmail.com>, 2024
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: IPFire Project\n"
|
||||
@@ -12,6 +13,8 @@ msgstr ""
|
||||
"PO-Revision-Date: 2017-09-20 09:45+0000\n"
|
||||
"Last-Translator: ipfire <qiwenqiu@yahoo.com.hk>\n"
|
||||
"Language-Team: Chinese (http://www.transifex.com/mstremer/ipfire/language/zh/)\n"
|
||||
"PO-Revision-Date: 2024-07-228 06:45+0000\n"
|
||||
"Last-Translator: bpfire <vincent.mc.li@gmail.com>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
@@ -84,355 +87,356 @@ msgstr "取消"
|
||||
#: dhcp.c:156
|
||||
msgid ""
|
||||
"The following fields are invalid:\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"以下填空字段无效:\n"
|
||||
|
||||
#: dhcp.c:159
|
||||
msgid "Start address"
|
||||
msgstr ""
|
||||
msgstr "起始地址"
|
||||
|
||||
#: dhcp.c:165
|
||||
msgid "End address"
|
||||
msgstr ""
|
||||
msgstr "结束地址"
|
||||
|
||||
#: dhcp.c:173 networking.c:755
|
||||
msgid "Primary DNS"
|
||||
msgstr ""
|
||||
msgstr "主域名服务器"
|
||||
|
||||
#: dhcp.c:182 networking.c:764
|
||||
msgid "Secondary DNS"
|
||||
msgstr ""
|
||||
msgstr "备域名服务器"
|
||||
|
||||
#: dhcp.c:189
|
||||
msgid "Default lease time"
|
||||
msgstr ""
|
||||
msgstr "默认租用时间"
|
||||
|
||||
#: dhcp.c:195
|
||||
msgid "Max. lease time"
|
||||
msgstr ""
|
||||
msgstr "最长租用时间"
|
||||
|
||||
#: domainname.c:42 main.c:70
|
||||
msgid "Domain name"
|
||||
msgstr ""
|
||||
msgstr "域名"
|
||||
|
||||
#: domainname.c:42
|
||||
msgid "Enter Domain name"
|
||||
msgstr ""
|
||||
msgstr "输入域名"
|
||||
|
||||
#: domainname.c:48
|
||||
msgid "Domain name cannot be empty."
|
||||
msgstr ""
|
||||
msgstr "域名不能为空。"
|
||||
|
||||
#: domainname.c:50
|
||||
msgid "Domain name cannot contain spaces."
|
||||
msgstr ""
|
||||
msgstr "域名不能包含空格。"
|
||||
|
||||
#: domainname.c:53
|
||||
msgid "Domain name may only contain letters, numbers, hyphens and periods."
|
||||
msgstr ""
|
||||
msgstr "域名只能包含字母、数字、连字符和句点。"
|
||||
|
||||
#: hostname.c:46 main.c:69
|
||||
msgid "Hostname"
|
||||
msgstr ""
|
||||
msgstr "主机名"
|
||||
|
||||
#: hostname.c:46
|
||||
msgid "Enter the machine's hostname."
|
||||
msgstr ""
|
||||
msgstr "输入主机的主机名。"
|
||||
|
||||
#: hostname.c:53
|
||||
msgid "Hostname cannot be empty."
|
||||
msgstr ""
|
||||
msgstr "主机名不能为空。"
|
||||
|
||||
#: hostname.c:55
|
||||
msgid "Hostname cannot contain spaces."
|
||||
msgstr ""
|
||||
msgstr "主机名不能包含空格。"
|
||||
|
||||
#: hostname.c:58
|
||||
msgid "Hostname may only contain letters, numbers and hyphens."
|
||||
msgstr ""
|
||||
msgstr "主机名只能包含字母、数字和连字符。"
|
||||
|
||||
#: keymap.c:84 main.c:67
|
||||
msgid "Keyboard mapping"
|
||||
msgstr ""
|
||||
msgstr "键盘映射"
|
||||
|
||||
#: keymap.c:85
|
||||
msgid "Choose the type of keyboard you are using from the list below."
|
||||
msgstr ""
|
||||
msgstr "从下面的列表中选择您正在使用的键盘类型。"
|
||||
|
||||
#: main.c:68 timezone.c:77
|
||||
msgid "Timezone"
|
||||
msgstr ""
|
||||
msgstr "时区"
|
||||
|
||||
#: main.c:71 networking.c:110 networking.c:115 networking.c:447
|
||||
msgid "Networking"
|
||||
msgstr ""
|
||||
msgstr "网络设置"
|
||||
|
||||
#: main.c:72 misc.c:147
|
||||
msgid "ISDN"
|
||||
msgstr ""
|
||||
msgstr "ISDN"
|
||||
|
||||
#: main.c:73
|
||||
msgid "'root' password"
|
||||
msgstr ""
|
||||
msgstr "‘root’ 密码"
|
||||
|
||||
#: main.c:74
|
||||
msgid "'admin' password"
|
||||
msgstr ""
|
||||
msgstr "‘admin’ 密码"
|
||||
|
||||
#: main.c:90
|
||||
msgid " <Tab>/<Alt-Tab> between elements | <Space> selects"
|
||||
msgstr ""
|
||||
msgstr " <Tab>/<Alt-Tab> 在元素间切换 | <Space> 选择"
|
||||
|
||||
#: main.c:97
|
||||
msgid "Section menu"
|
||||
msgstr ""
|
||||
msgstr "部分菜单"
|
||||
|
||||
#: main.c:98
|
||||
msgid "Select the item you wish to configure."
|
||||
msgstr ""
|
||||
msgstr "选择您希望配置的项目。"
|
||||
|
||||
#: main.c:99
|
||||
msgid "Quit"
|
||||
msgstr ""
|
||||
msgstr "退出"
|
||||
|
||||
#: main.c:172
|
||||
msgid "Setup is complete."
|
||||
msgstr ""
|
||||
msgstr "设置已完成。"
|
||||
|
||||
#: main.c:174 netstuff.c:733 networking.c:560 networking.c:653
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
msgstr "警告"
|
||||
|
||||
#: main.c:175
|
||||
msgid ""
|
||||
"Initial setup was not entirely complete. You must ensure that Setup is "
|
||||
"properly finished by running setup again at the shell."
|
||||
msgstr ""
|
||||
"初始setup并未完全完成。您必须确保通过在shell中再次运行setup来正确完成设置。"
|
||||
|
||||
#: misc.c:62
|
||||
#, c-format
|
||||
msgid "Unable to write %s/main/hostname.conf"
|
||||
msgstr ""
|
||||
msgstr "无法写入 %s/main/hostname.conf"
|
||||
|
||||
#: misc.c:71
|
||||
msgid "Unable to open main hosts file."
|
||||
msgstr ""
|
||||
msgstr "无法打开主机文件。"
|
||||
|
||||
#: misc.c:76
|
||||
msgid "Unable to write /etc/hosts."
|
||||
msgstr ""
|
||||
msgstr "无法写入 /etc/hosts。"
|
||||
|
||||
#: misc.c:117
|
||||
msgid "Unable to write /etc/hosts.deny."
|
||||
msgstr ""
|
||||
msgstr "无法写入 /etc/hosts.deny。"
|
||||
|
||||
#: misc.c:125
|
||||
msgid "Unable to write /etc/hosts.allow."
|
||||
msgstr ""
|
||||
msgstr "无法写入 /etc/hosts.allow。"
|
||||
|
||||
#: misc.c:136
|
||||
msgid "Unable to set hostname."
|
||||
msgstr ""
|
||||
msgstr "无法设置主机名。"
|
||||
|
||||
#: misc.c:147
|
||||
msgid "Scanning and configuring ISDN devices."
|
||||
msgstr ""
|
||||
msgstr "正在扫描和配置ISDN设备。"
|
||||
|
||||
#: misc.c:148
|
||||
msgid "Unable to scan for ISDN devices."
|
||||
msgstr ""
|
||||
msgstr "无法扫描ISDN设备。"
|
||||
|
||||
#: netstuff.c:86
|
||||
#, c-format
|
||||
msgid "Interface - %s"
|
||||
msgstr ""
|
||||
msgstr "接口 - %s"
|
||||
|
||||
#: netstuff.c:91
|
||||
#, c-format
|
||||
msgid "Enter the IP address information for the %s interface."
|
||||
msgstr ""
|
||||
msgstr "为 %s 接口输入IP地址信息。"
|
||||
|
||||
#: netstuff.c:103
|
||||
msgid "Static"
|
||||
msgstr ""
|
||||
msgstr "静态"
|
||||
|
||||
#: netstuff.c:104
|
||||
msgid "DHCP"
|
||||
msgstr ""
|
||||
msgstr "DHCP"
|
||||
|
||||
#: netstuff.c:105
|
||||
msgid "PPP DIALUP (PPPoE, modem, ATM ...)"
|
||||
msgstr ""
|
||||
msgstr "PPP拨号连接(PPPoE,调制解调器,ATM ...)"
|
||||
|
||||
#: netstuff.c:113
|
||||
msgid "DHCP Hostname:"
|
||||
msgstr ""
|
||||
msgstr "DHCP主机名:"
|
||||
|
||||
#: netstuff.c:115
|
||||
msgid "Force DHCP MTU:"
|
||||
msgstr ""
|
||||
msgstr "强制DHCP MTU:"
|
||||
|
||||
#: netstuff.c:134
|
||||
msgid "IP address:"
|
||||
msgstr ""
|
||||
msgstr "IP地址:"
|
||||
|
||||
#: netstuff.c:146
|
||||
msgid "Network mask:"
|
||||
msgstr ""
|
||||
msgstr "子网掩码:"
|
||||
|
||||
#: netstuff.c:173 networking.c:749
|
||||
msgid "The following fields are invalid:"
|
||||
msgstr ""
|
||||
msgstr "以下字段无效:"
|
||||
|
||||
#: netstuff.c:183
|
||||
msgid "IP address"
|
||||
msgstr ""
|
||||
msgstr "IP地址"
|
||||
|
||||
#: netstuff.c:189
|
||||
msgid "Network mask"
|
||||
msgstr ""
|
||||
msgstr "子网掩码"
|
||||
|
||||
#: netstuff.c:198
|
||||
msgid "DHCP hostname"
|
||||
msgstr ""
|
||||
msgstr "DHCP主机名"
|
||||
|
||||
#: netstuff.c:396 netstuff.c:709
|
||||
msgid "Unset"
|
||||
msgstr ""
|
||||
msgstr "未设置"
|
||||
|
||||
#: netstuff.c:669
|
||||
#, c-format
|
||||
msgid "Please choose a networkcard for the following interface - %s."
|
||||
msgstr ""
|
||||
msgid "Please choose a network card for the following interface - %s."
|
||||
msgstr "请选择以下接口的网络卡 - %s。"
|
||||
|
||||
#: netstuff.c:672
|
||||
msgid "Extended Network Menu"
|
||||
msgstr ""
|
||||
msgstr "扩展网络菜单"
|
||||
|
||||
#: netstuff.c:673 networking.c:520
|
||||
msgid "Select"
|
||||
msgstr ""
|
||||
msgstr "选择"
|
||||
|
||||
#: netstuff.c:673
|
||||
msgid "Identify"
|
||||
msgstr ""
|
||||
msgstr "识别"
|
||||
|
||||
#: netstuff.c:678
|
||||
msgid "Device Identification"
|
||||
msgstr ""
|
||||
msgstr "设备识别"
|
||||
|
||||
#: netstuff.c:678
|
||||
msgid "The lights on the selected port should flash now for 10 seconds..."
|
||||
msgstr ""
|
||||
msgstr "选定端口上的指示灯应该现在闪烁10秒钟..."
|
||||
|
||||
#: netstuff.c:679
|
||||
msgid "Identification is not supported by this interface."
|
||||
msgstr ""
|
||||
msgstr "此接口不支持识别功能。"
|
||||
|
||||
#: netstuff.c:691
|
||||
msgid "There are no unassigned interfaces on your system."
|
||||
msgstr ""
|
||||
msgstr "系统中没有未分配的接口。"
|
||||
|
||||
#: netstuff.c:732
|
||||
#, c-format
|
||||
msgid "Do you really want to remove the assigned %s interface?"
|
||||
msgstr ""
|
||||
msgstr "您确定要移除分配的 %s 接口吗?"
|
||||
|
||||
#: netstuff.c:755
|
||||
msgid "Select network driver"
|
||||
msgstr ""
|
||||
msgstr "选择网络驱动程序"
|
||||
|
||||
#: netstuff.c:755
|
||||
msgid "Set additional module parameters"
|
||||
msgstr ""
|
||||
msgstr "设置额外的模块参数"
|
||||
|
||||
#: netstuff.c:762
|
||||
msgid "Loading module..."
|
||||
msgstr ""
|
||||
msgstr "正在加载模块..."
|
||||
|
||||
#: netstuff.c:777
|
||||
msgid "Unable to load driver module."
|
||||
msgstr ""
|
||||
msgstr "无法加载驱动模块。"
|
||||
|
||||
#: netstuff.c:780
|
||||
msgid "Module name cannot be blank."
|
||||
msgstr ""
|
||||
msgstr "模块名称不能为空。"
|
||||
|
||||
#: networking.c:110
|
||||
msgid "Stopping network..."
|
||||
msgstr ""
|
||||
msgstr "停止网络..."
|
||||
|
||||
#: networking.c:115
|
||||
msgid "Restarting network..."
|
||||
msgstr ""
|
||||
msgstr "重启网络..."
|
||||
|
||||
#: networking.c:146
|
||||
msgid "No GREEN interface assigned."
|
||||
msgstr ""
|
||||
msgstr "未分配 GREEN 接口。"
|
||||
|
||||
#: networking.c:152
|
||||
msgid "Missing an IP address on GREEN."
|
||||
msgstr ""
|
||||
msgstr "GREEN 上缺少IP地址。"
|
||||
|
||||
#: networking.c:163
|
||||
msgid "Error"
|
||||
msgstr ""
|
||||
msgstr "错误"
|
||||
|
||||
#: networking.c:163
|
||||
msgid "Ignore"
|
||||
msgstr ""
|
||||
msgstr "忽略"
|
||||
|
||||
#: networking.c:164
|
||||
msgid "No RED interface assigned."
|
||||
msgstr ""
|
||||
msgstr "未分配 RED 接口。"
|
||||
|
||||
#: networking.c:173
|
||||
msgid "Missing an IP address on RED."
|
||||
msgstr ""
|
||||
msgstr "RED 上缺少IP地址。"
|
||||
|
||||
#: networking.c:183
|
||||
msgid "No ORANGE interface assigned."
|
||||
msgstr ""
|
||||
msgstr "未分配 ORANGE 接口。"
|
||||
|
||||
#: networking.c:189
|
||||
msgid "Missing an IP address on ORANGE."
|
||||
msgstr ""
|
||||
msgstr "ORANGE 上缺少IP地址。"
|
||||
|
||||
#: networking.c:199
|
||||
msgid "No BLUE interface assigned."
|
||||
msgstr ""
|
||||
msgstr "未分配 BLUE 接口。"
|
||||
|
||||
#: networking.c:205
|
||||
msgid "Missing an IP address on BLUE."
|
||||
msgstr ""
|
||||
msgstr "BLUE 上缺少IP地址。"
|
||||
|
||||
#: networking.c:217
|
||||
msgid "Misssing DNS."
|
||||
msgstr ""
|
||||
msgid "Missing DNS."
|
||||
msgstr "缺少DNS。"
|
||||
|
||||
#: networking.c:224
|
||||
msgid "Missing Default Gateway."
|
||||
msgstr ""
|
||||
msgstr "缺少默认网关。"
|
||||
|
||||
#: networking.c:237 networking.c:304
|
||||
msgid "Network configuration type"
|
||||
msgstr ""
|
||||
msgstr "网络配置类型"
|
||||
|
||||
#: networking.c:238 networking.c:409
|
||||
msgid "Drivers and card assignments"
|
||||
msgstr ""
|
||||
msgstr "驱动程序和网卡分配"
|
||||
|
||||
#: networking.c:239 networking.c:640
|
||||
msgid "Address settings"
|
||||
msgstr ""
|
||||
msgstr "地址设置"
|
||||
|
||||
#: networking.c:240 networking.c:743
|
||||
msgid "DNS and Gateway settings"
|
||||
msgstr ""
|
||||
msgstr "DNS和网关设置"
|
||||
|
||||
#: networking.c:260
|
||||
msgid "When configuration is complete, a network restart will be required."
|
||||
msgstr ""
|
||||
msgstr "配置完成后,需要重新启动网络。"
|
||||
|
||||
#: networking.c:267
|
||||
#, c-format
|
||||
@@ -441,14 +445,17 @@ msgid ""
|
||||
"\n"
|
||||
"%s"
|
||||
msgstr ""
|
||||
"当前配置:%s\n"
|
||||
"\n"
|
||||
"%s"
|
||||
|
||||
#: networking.c:268
|
||||
msgid "Network configuration menu"
|
||||
msgstr ""
|
||||
msgstr "网络配置菜单"
|
||||
|
||||
#: networking.c:269 networking.c:520 networking.c:642
|
||||
msgid "Done"
|
||||
msgstr ""
|
||||
msgstr "完成"
|
||||
|
||||
#: networking.c:300
|
||||
#, c-format
|
||||
@@ -458,6 +465,7 @@ msgid ""
|
||||
"setting, a network restart will be required, and you will have to "
|
||||
"reconfigure the network driver assignments."
|
||||
msgstr ""
|
||||
"选择 %s 的网络配置。以下配置类型列出了已连接以太网的接口。如果更改此设置,将需要重新启动网络,并且您将需要重新配置网络驱动程序分配。"
|
||||
|
||||
#: networking.c:307
|
||||
#, c-format
|
||||
@@ -466,34 +474,41 @@ msgid ""
|
||||
"\n"
|
||||
"Needed: %d - Available: %d\n"
|
||||
msgstr ""
|
||||
"没有足够的网卡供您选择。\n"
|
||||
"\n"
|
||||
"所需:%d - 可用:%d\n"
|
||||
|
||||
#: networking.c:359
|
||||
msgid ""
|
||||
"Configure network drivers, and which interface each card is assigned to. The current configuration is as follows:\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"配置网络驱动程序及每张网卡分配的接口。当前配置如下:\n"
|
||||
"\n"
|
||||
|
||||
#: networking.c:408
|
||||
msgid "Do you wish to change these settings?"
|
||||
msgstr ""
|
||||
msgstr "您是否希望更改这些设置?"
|
||||
|
||||
#: networking.c:447
|
||||
msgid "Restarting non-local network..."
|
||||
msgstr ""
|
||||
msgstr "正在重新启动非本地网络..."
|
||||
|
||||
#: networking.c:464
|
||||
msgid ""
|
||||
"Please choose the interface you wish to change.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
"请选择您希望更改的接口。\n"
|
||||
"\n"
|
||||
|
||||
#: networking.c:519
|
||||
msgid "Assigned Cards"
|
||||
msgstr ""
|
||||
msgstr "已分配的网卡"
|
||||
|
||||
#: networking.c:520
|
||||
msgid "Remove"
|
||||
msgstr ""
|
||||
msgstr "移除"
|
||||
|
||||
#: networking.c:556 networking.c:649
|
||||
#, c-format
|
||||
@@ -503,45 +518,48 @@ msgid ""
|
||||
"on the new IP. This is a risky operation, and should only be attempted if "
|
||||
"you have physical access to the machine, should something go wrong."
|
||||
msgstr ""
|
||||
"如果您更改此IP地址,并且您是远程登录的,您将会断开与 %s 机器的连接,您需要在新IP上重新连接。这是一项风险较高的操作,只有在您有机器的物理访问权限时,才应尝试执行,以防出现问题。"
|
||||
|
||||
#: networking.c:641
|
||||
msgid "Select the interface you wish to reconfigure."
|
||||
msgstr ""
|
||||
msgstr "选择您希望重新配置的接口。"
|
||||
|
||||
#: networking.c:729
|
||||
msgid "Default gateway:"
|
||||
msgstr ""
|
||||
msgstr "默认网关:"
|
||||
|
||||
#: networking.c:744
|
||||
msgid ""
|
||||
"Enter the DNS and gateway information. These settings are used only with "
|
||||
"Static IP (and DHCP if DNS set) on the RED interface."
|
||||
msgstr ""
|
||||
"输入DNS和网关信息。这些设置仅用于RED接口上的静态IP(以及如果设置了DNS的话,DHCP也适用)。"
|
||||
|
||||
#: networking.c:773
|
||||
msgid "Default gateway"
|
||||
msgstr ""
|
||||
msgstr "默认网关"
|
||||
|
||||
#: networking.c:780
|
||||
msgid "Secondary DNS specified without a Primary DNS"
|
||||
msgstr ""
|
||||
msgstr "指定了次要DNS但未指定主要DNS"
|
||||
|
||||
#: passwords.c:33
|
||||
msgid ""
|
||||
"Enter the 'root' user password. Login as this user for commandline access."
|
||||
msgstr ""
|
||||
"输入 'root' 用户密码。以此用户登录以获取命令行访问权限。"
|
||||
|
||||
#: passwords.c:38 passwords.c:61
|
||||
msgid "Setting password"
|
||||
msgstr ""
|
||||
msgstr "设置密码"
|
||||
|
||||
#: passwords.c:38
|
||||
msgid "Setting 'root' password...."
|
||||
msgstr ""
|
||||
msgstr "正在设置 'root' 密码...."
|
||||
|
||||
#: passwords.c:39
|
||||
msgid "Problem setting 'root' password."
|
||||
msgstr ""
|
||||
msgstr "设置 'root' 密码时出现问题。"
|
||||
|
||||
#: passwords.c:53
|
||||
#, c-format
|
||||
@@ -549,37 +567,38 @@ msgid ""
|
||||
"Enter %s 'admin' user password. This is the user to use for logging into the"
|
||||
" %s web administration pages."
|
||||
msgstr ""
|
||||
"输入 %s 'admin' 用户密码。此用户用于登录到 %s 网页管理页面。"
|
||||
|
||||
#: passwords.c:60
|
||||
#, c-format
|
||||
msgid "Setting %s 'admin' user password..."
|
||||
msgstr ""
|
||||
msgstr "正在设置 %s 'admin' 用户密码..."
|
||||
|
||||
#: passwords.c:62
|
||||
#, c-format
|
||||
msgid "Problem setting %s 'admin' user password."
|
||||
msgstr ""
|
||||
msgstr "设置 %s 'admin' 用户密码时出现问题。"
|
||||
|
||||
#: passwords.c:76
|
||||
msgid "Password:"
|
||||
msgstr ""
|
||||
msgstr "密码:"
|
||||
|
||||
#: passwords.c:77
|
||||
msgid "Again:"
|
||||
msgstr ""
|
||||
msgstr "再次输入:"
|
||||
|
||||
#: passwords.c:95
|
||||
msgid "Password cannot be blank."
|
||||
msgstr ""
|
||||
msgstr "密码不能为空。"
|
||||
|
||||
#: passwords.c:102
|
||||
msgid "Passwords do not match."
|
||||
msgstr ""
|
||||
msgstr "密码不匹配。"
|
||||
|
||||
#: passwords.c:109
|
||||
msgid "Password cannot contain spaces."
|
||||
msgstr ""
|
||||
msgstr "密码不能包含空格。"
|
||||
|
||||
#: timezone.c:77
|
||||
msgid "Choose the timezone you are in from the list below."
|
||||
msgstr ""
|
||||
msgstr "从下面的列表中选择您所在的时区。"
|
||||
|
||||