diff options
33 files changed, 1264 insertions, 1181 deletions
diff --git a/data/op-mode-standardized.json b/data/op-mode-standardized.json index 9500d3aa7..ec950765d 100644 --- a/data/op-mode-standardized.json +++ b/data/op-mode-standardized.json @@ -1,8 +1,11 @@ [ +"bgp.py", "bridge.py", "conntrack.py", "container.py", "cpu.py", +"dhcp.py", +"log.py", "memory.py", "nat.py", "neighbor.py", diff --git a/data/templates/ipsec/charon/eap-radius.conf.j2 b/data/templates/ipsec/charon/eap-radius.conf.j2 index 8495011fe..364377473 100644 --- a/data/templates/ipsec/charon/eap-radius.conf.j2 +++ b/data/templates/ipsec/charon/eap-radius.conf.j2 @@ -49,8 +49,10 @@ eap-radius { # Base to use for calculating exponential back off. # retransmit_base = 1.4 +{% if remote_access.radius.timeout is vyos_defined %} # Timeout in seconds before sending first retransmit. - # retransmit_timeout = 2.0 + retransmit_timeout = {{ remote_access.radius.timeout | float }} +{% endif %} # Number of times to retransmit a packet before giving up. # retransmit_tries = 4 diff --git a/debian/control b/debian/control index 16b7ee814..d7cd5b688 100644 --- a/debian/control +++ b/debian/control @@ -25,6 +25,7 @@ Build-Depends: python3-setuptools, python3-sphinx, python3-xmltodict, + python3-pyhumps, quilt, whois Standards-Version: 3.9.6 @@ -131,6 +132,7 @@ Depends: python3-netifaces, python3-paramiko, python3-psutil, + python3-pyhumps, python3-pystache, python3-pyudev, python3-six, diff --git a/interface-definitions/firewall.xml.in b/interface-definitions/firewall.xml.in index 2d8f17351..2ebce79e5 100644 --- a/interface-definitions/firewall.xml.in +++ b/interface-definitions/firewall.xml.in @@ -218,7 +218,7 @@ <properties> <help>Mac-group member</help> <valueHelp> - <format><MAC address></format> + <format>macaddr</format> <description>MAC address to match</description> </valueHelp> <constraint> diff --git a/interface-definitions/include/firewall/common-rule.xml.i b/interface-definitions/include/firewall/common-rule.xml.i index a4f66f5cb..75ad427f9 100644 --- a/interface-definitions/include/firewall/common-rule.xml.i +++ b/interface-definitions/include/firewall/common-rule.xml.i @@ -219,22 +219,7 @@ <children> #include <include/firewall/address.xml.i> #include <include/firewall/source-destination-group.xml.i> - <leafNode name="mac-address"> - <properties> - <help>Source MAC address</help> - <valueHelp> - <format><MAC address></format> - <description>MAC address to match</description> - </valueHelp> - <valueHelp> - <format>!<MAC address></format> - <description>Match everything except the specified MAC address</description> - </valueHelp> - <constraint> - <validator name="mac-address-firewall"/> - </constraint> - </properties> - </leafNode> + #include <include/firewall/mac-address.xml.i> #include <include/firewall/port.xml.i> </children> </node> diff --git a/interface-definitions/include/firewall/mac-address.xml.i b/interface-definitions/include/firewall/mac-address.xml.i new file mode 100644 index 000000000..db3e1e312 --- /dev/null +++ b/interface-definitions/include/firewall/mac-address.xml.i @@ -0,0 +1,19 @@ +<!-- include start from firewall/mac-address.xml.i --> +<leafNode name="mac-address"> + <properties> + <help>MAC address</help> + <valueHelp> + <format>macaddr</format> + <description>MAC address to match</description> + </valueHelp> + <valueHelp> + <format>!macaddr</format> + <description>Match everything except the specified MAC address</description> + </valueHelp> + <constraint> + <validator name="mac-address"/> + <validator name="mac-address-exclude"/> + </constraint> + </properties> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/include/policy/route-common-rule-ipv6.xml.i b/interface-definitions/include/policy/route-common-rule-ipv6.xml.i deleted file mode 100644 index 662206336..000000000 --- a/interface-definitions/include/policy/route-common-rule-ipv6.xml.i +++ /dev/null @@ -1,557 +0,0 @@ -<!-- include start from policy/route-common-rule.xml.i --> -#include <include/policy/route-rule-action.xml.i> -#include <include/generic-description.xml.i> -<leafNode name="disable"> - <properties> - <help>Option to disable firewall rule</help> - <valueless/> - </properties> -</leafNode> -<node name="fragment"> - <properties> - <help>IP fragment match</help> - </properties> - <children> - <leafNode name="match-frag"> - <properties> - <help>Second and further fragments of fragmented packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="match-non-frag"> - <properties> - <help>Head fragments or unfragmented packets</help> - <valueless/> - </properties> - </leafNode> - </children> -</node> -<node name="ipsec"> - <properties> - <help>Inbound IPsec packets</help> - </properties> - <children> - <leafNode name="match-ipsec"> - <properties> - <help>Inbound IPsec packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="match-none"> - <properties> - <help>Inbound non-IPsec packets</help> - <valueless/> - </properties> - </leafNode> - </children> -</node> -<node name="limit"> - <properties> - <help>Rate limit using a token bucket filter</help> - </properties> - <children> - <leafNode name="burst"> - <properties> - <help>Maximum number of packets to allow in excess of rate</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Maximum number of packets to allow in excess of rate</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - <leafNode name="rate"> - <properties> - <help>Maximum average matching rate</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Maximum average matching rate</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<leafNode name="log"> - <properties> - <help>Option to log packets matching rule</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable log</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable log</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> -</leafNode> -<leafNode name="protocol"> - <properties> - <help>Protocol to match (protocol name, number, or "all")</help> - <completionHelp> - <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script> - </completionHelp> - <valueHelp> - <format>all</format> - <description>All IP protocols</description> - </valueHelp> - <valueHelp> - <format>tcp_udp</format> - <description>Both TCP and UDP</description> - </valueHelp> - <valueHelp> - <format>0-255</format> - <description>IP protocol number</description> - </valueHelp> - <valueHelp> - <format>!<protocol></format> - <description>IP protocol number</description> - </valueHelp> - <constraint> - <validator name="ip-protocol"/> - </constraint> - </properties> - <defaultValue>all</defaultValue> -</leafNode> -<node name="recent"> - <properties> - <help>Parameters for matching recently seen sources</help> - </properties> - <children> - <leafNode name="count"> - <properties> - <help>Source addresses seen more than N times</help> - <valueHelp> - <format>u32:1-255</format> - <description>Source addresses seen more than N times</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-255"/> - </constraint> - </properties> - </leafNode> - <leafNode name="time"> - <properties> - <help>Source addresses seen in the last N seconds</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Source addresses seen in the last N seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<node name="set"> - <properties> - <help>Packet modifications</help> - </properties> - <children> - <leafNode name="dscp"> - <properties> - <help>Packet Differentiated Services Codepoint (DSCP)</help> - <valueHelp> - <format>u32:0-63</format> - <description>DSCP number</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-63"/> - </constraint> - </properties> - </leafNode> - <leafNode name="mark"> - <properties> - <help>Packet marking</help> - <valueHelp> - <format>u32:1-2147483647</format> - <description>Packet marking</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-2147483647"/> - </constraint> - </properties> - </leafNode> - <leafNode name="table"> - <properties> - <help>Routing table to forward packet with</help> - <valueHelp> - <format>u32:1-200</format> - <description>Table number</description> - </valueHelp> - <valueHelp> - <format>main</format> - <description>Main table</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-200"/> - <regex>(main)</regex> - </constraint> - <completionHelp> - <list>main</list> - <path>protocols static table</path> - </completionHelp> - </properties> - </leafNode> - <leafNode name="tcp-mss"> - <properties> - <help>TCP Maximum Segment Size</help> - <valueHelp> - <format>u32:500-1460</format> - <description>Explicitly set TCP MSS value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 500-1460"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<node name="source"> - <properties> - <help>Source parameters</help> - </properties> - <children> - #include <include/firewall/address-ipv6.xml.i> - #include <include/firewall/source-destination-group.xml.i> - <leafNode name="mac-address"> - <properties> - <help>Source MAC address</help> - <valueHelp> - <format><MAC address></format> - <description>MAC address to match</description> - </valueHelp> - <valueHelp> - <format>!<MAC address></format> - <description>Match everything except the specified MAC address</description> - </valueHelp> - <constraint> - <validator name="mac-address-firewall"/> - </constraint> - </properties> - </leafNode> - #include <include/firewall/port.xml.i> - </children> -</node> -<node name="state"> - <properties> - <help>Session state</help> - </properties> - <children> - <leafNode name="established"> - <properties> - <help>Established state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="invalid"> - <properties> - <help>Invalid state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="new"> - <properties> - <help>New state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="related"> - <properties> - <help>Related state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - </children> -</node> -#include <include/firewall/tcp-flags.xml.i> -<node name="time"> - <properties> - <help>Time to match rule</help> - </properties> - <children> - <leafNode name="monthdays"> - <properties> - <help>Monthdays to match rule on</help> - </properties> - </leafNode> - <leafNode name="startdate"> - <properties> - <help>Date to start matching rule</help> - </properties> - </leafNode> - <leafNode name="starttime"> - <properties> - <help>Time of day to start matching rule</help> - </properties> - </leafNode> - <leafNode name="stopdate"> - <properties> - <help>Date to stop matching rule</help> - </properties> - </leafNode> - <leafNode name="stoptime"> - <properties> - <help>Time of day to stop matching rule</help> - </properties> - </leafNode> - <leafNode name="utc"> - <properties> - <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="weekdays"> - <properties> - <help>Weekdays to match rule on</help> - </properties> - </leafNode> - </children> -</node> -<node name="icmpv6"> - <properties> - <help>ICMPv6 type and code information</help> - </properties> - <children> - <leafNode name="type"> - <properties> - <help>ICMP type-name</help> - <completionHelp> - <list>any echo-reply pong destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS host-redirect echo-request ping router-advertisement router-solicitation time-exceeded ttl-exceeded ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply packet-too-big</list> - </completionHelp> - <valueHelp> - <format>any</format> - <description>Any ICMP type/code</description> - </valueHelp> - <valueHelp> - <format>echo-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>pong</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>destination-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>protocol-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>port-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>fragmentation-needed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>source-route-failed</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-unknown</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-host-unreachable</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>communication-prohibited</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-precedence-violation</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>precedence-cutoff</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>source-quench</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>host-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS-network-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>TOS host-redirect</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>echo-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ping</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>router-advertisement</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>router-solicitation</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>time-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-exceeded</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-transit</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ttl-zero-during-reassembly</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>parameter-problem</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>ip-header-bad</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>required-option-missing</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>timestamp-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>timestamp-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>address-mask-request</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>address-mask-reply</format> - <description>ICMP type/code name</description> - </valueHelp> - <valueHelp> - <format>packet-too-big</format> - <description>ICMP type/code name</description> - </valueHelp> - <constraint> - <regex>(any|echo-reply|pong|destination-unreachable|network-unreachable|host-unreachable|protocol-unreachable|port-unreachable|fragmentation-needed|source-route-failed|network-unknown|host-unknown|network-prohibited|host-prohibited|TOS-network-unreachable|TOS-host-unreachable|communication-prohibited|host-precedence-violation|precedence-cutoff|source-quench|redirect|network-redirect|host-redirect|TOS-network-redirect|TOS host-redirect|echo-request|ping|router-advertisement|router-solicitation|time-exceeded|ttl-exceeded|ttl-zero-during-transit|ttl-zero-during-reassembly|parameter-problem|ip-header-bad|required-option-missing|timestamp-request|timestamp-reply|address-mask-request|address-mask-reply|packet-too-big)</regex> - <validator name="numeric" argument="--range 0-255"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<!-- include end --> diff --git a/interface-definitions/include/policy/route-common-rule.xml.i b/interface-definitions/include/policy/route-common.xml.i index 35fccca50..8b959c2a4 100644 --- a/interface-definitions/include/policy/route-common-rule.xml.i +++ b/interface-definitions/include/policy/route-common.xml.i @@ -1,406 +1,348 @@ -<!-- include start from policy/route-common-rule.xml.i --> -#include <include/policy/route-rule-action.xml.i> -#include <include/generic-description.xml.i> -<leafNode name="disable"> - <properties> - <help>Option to disable firewall rule</help> - <valueless/> - </properties> -</leafNode> -<node name="fragment"> - <properties> - <help>IP fragment match</help> - </properties> - <children> - <leafNode name="match-frag"> - <properties> - <help>Second and further fragments of fragmented packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="match-non-frag"> - <properties> - <help>Head fragments or unfragmented packets</help> - <valueless/> - </properties> - </leafNode> - </children> -</node> -<node name="ipsec"> - <properties> - <help>Inbound IPsec packets</help> - </properties> - <children> - <leafNode name="match-ipsec"> - <properties> - <help>Inbound IPsec packets</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="match-none"> - <properties> - <help>Inbound non-IPsec packets</help> - <valueless/> - </properties> - </leafNode> - </children> -</node> -<node name="limit"> - <properties> - <help>Rate limit using a token bucket filter</help> - </properties> - <children> - <leafNode name="burst"> - <properties> - <help>Maximum number of packets to allow in excess of rate</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Maximum number of packets to allow in excess of rate</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - <leafNode name="rate"> - <properties> - <help>Maximum average matching rate</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Maximum average matching rate</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<leafNode name="log"> - <properties> - <help>Option to log packets matching rule</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable log</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable log</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> -</leafNode> -<leafNode name="protocol"> - <properties> - <help>Protocol to match (protocol name, number, or "all")</help> - <completionHelp> - <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script> - </completionHelp> - <valueHelp> - <format>all</format> - <description>All IP protocols</description> - </valueHelp> - <valueHelp> - <format>tcp_udp</format> - <description>Both TCP and UDP</description> - </valueHelp> - <valueHelp> - <format>0-255</format> - <description>IP protocol number</description> - </valueHelp> - <valueHelp> - <format>!<protocol></format> - <description>IP protocol number</description> - </valueHelp> - <constraint> - <validator name="ip-protocol"/> - </constraint> - </properties> - <defaultValue>all</defaultValue> -</leafNode> -<node name="recent"> - <properties> - <help>Parameters for matching recently seen sources</help> - </properties> - <children> - <leafNode name="count"> - <properties> - <help>Source addresses seen more than N times</help> - <valueHelp> - <format>u32:1-255</format> - <description>Source addresses seen more than N times</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-255"/> - </constraint> - </properties> - </leafNode> - <leafNode name="time"> - <properties> - <help>Source addresses seen in the last N seconds</help> - <valueHelp> - <format>u32:0-4294967295</format> - <description>Source addresses seen in the last N seconds</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-4294967295"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<node name="set"> - <properties> - <help>Packet modifications</help> - </properties> - <children> - <leafNode name="dscp"> - <properties> - <help>Packet Differentiated Services Codepoint (DSCP)</help> - <valueHelp> - <format>u32:0-63</format> - <description>DSCP number</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-63"/> - </constraint> - </properties> - </leafNode> - <leafNode name="mark"> - <properties> - <help>Packet marking</help> - <valueHelp> - <format>u32:1-2147483647</format> - <description>Packet marking</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-2147483647"/> - </constraint> - </properties> - </leafNode> - <leafNode name="table"> - <properties> - <help>Routing table to forward packet with</help> - <valueHelp> - <format>u32:1-200</format> - <description>Table number</description> - </valueHelp> - <valueHelp> - <format>main</format> - <description>Main table</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-200"/> - <regex>(main)</regex> - </constraint> - <completionHelp> - <list>main</list> - <path>protocols static table</path> - </completionHelp> - </properties> - </leafNode> - <leafNode name="tcp-mss"> - <properties> - <help>TCP Maximum Segment Size</help> - <valueHelp> - <format>u32:500-1460</format> - <description>Explicitly set TCP MSS value</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 500-1460"/> - </constraint> - </properties> - </leafNode> - </children> -</node> -<node name="source"> - <properties> - <help>Source parameters</help> - </properties> - <children> - #include <include/firewall/address.xml.i> - #include <include/firewall/source-destination-group.xml.i> - <leafNode name="mac-address"> - <properties> - <help>Source MAC address</help> - <valueHelp> - <format><MAC address></format> - <description>MAC address to match</description> - </valueHelp> - <valueHelp> - <format>!<MAC address></format> - <description>Match everything except the specified MAC address</description> - </valueHelp> - <constraint> - <validator name="mac-address-firewall"/> - </constraint> - </properties> - </leafNode> - #include <include/firewall/port.xml.i> - </children> -</node> -<node name="state"> - <properties> - <help>Session state</help> - </properties> - <children> - <leafNode name="established"> - <properties> - <help>Established state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="invalid"> - <properties> - <help>Invalid state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="new"> - <properties> - <help>New state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - <leafNode name="related"> - <properties> - <help>Related state</help> - <completionHelp> - <list>enable disable</list> - </completionHelp> - <valueHelp> - <format>enable</format> - <description>Enable</description> - </valueHelp> - <valueHelp> - <format>disable</format> - <description>Disable</description> - </valueHelp> - <constraint> - <regex>(enable|disable)</regex> - </constraint> - </properties> - </leafNode> - </children> -</node> -#include <include/firewall/tcp-flags.xml.i> -<node name="time"> - <properties> - <help>Time to match rule</help> - </properties> - <children> - <leafNode name="monthdays"> - <properties> - <help>Monthdays to match rule on</help> - </properties> - </leafNode> - <leafNode name="startdate"> - <properties> - <help>Date to start matching rule</help> - </properties> - </leafNode> - <leafNode name="starttime"> - <properties> - <help>Time of day to start matching rule</help> - </properties> - </leafNode> - <leafNode name="stopdate"> - <properties> - <help>Date to stop matching rule</help> - </properties> - </leafNode> - <leafNode name="stoptime"> - <properties> - <help>Time of day to stop matching rule</help> - </properties> - </leafNode> - <leafNode name="utc"> - <properties> - <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help> - <valueless/> - </properties> - </leafNode> - <leafNode name="weekdays"> - <properties> - <help>Weekdays to match rule on</help> - </properties> - </leafNode> - </children> -</node> -<node name="icmp"> - <properties> - <help>ICMP type and code information</help> - </properties> - <children> - <leafNode name="code"> - <properties> - <help>ICMP code (0-255)</help> - <valueHelp> - <format>u32:0-255</format> - <description>ICMP code (0-255)</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-255"/> - </constraint> - </properties> - </leafNode> - <leafNode name="type"> - <properties> - <help>ICMP type (0-255)</help> - <valueHelp> - <format>u32:0-255</format> - <description>ICMP type (0-255)</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 0-255"/> - </constraint> - </properties> - </leafNode> - #include <include/firewall/icmp-type-name.xml.i> - </children> -</node> -<!-- include end --> +<!-- include start from policy/route-common.xml.i -->
+#include <include/policy/route-rule-action.xml.i>
+#include <include/generic-description.xml.i>
+<leafNode name="disable">
+ <properties>
+ <help>Option to disable firewall rule</help>
+ <valueless/>
+ </properties>
+</leafNode>
+<node name="fragment">
+ <properties>
+ <help>IP fragment match</help>
+ </properties>
+ <children>
+ <leafNode name="match-frag">
+ <properties>
+ <help>Second and further fragments of fragmented packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="match-non-frag">
+ <properties>
+ <help>Head fragments or unfragmented packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="ipsec">
+ <properties>
+ <help>Inbound IPsec packets</help>
+ </properties>
+ <children>
+ <leafNode name="match-ipsec">
+ <properties>
+ <help>Inbound IPsec packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="match-none">
+ <properties>
+ <help>Inbound non-IPsec packets</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="limit">
+ <properties>
+ <help>Rate limit using a token bucket filter</help>
+ </properties>
+ <children>
+ <leafNode name="burst">
+ <properties>
+ <help>Maximum number of packets to allow in excess of rate</help>
+ <valueHelp>
+ <format>u32:0-4294967295</format>
+ <description>Maximum number of packets to allow in excess of rate</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="rate">
+ <properties>
+ <help>Maximum average matching rate</help>
+ <valueHelp>
+ <format>u32:0-4294967295</format>
+ <description>Maximum average matching rate</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<leafNode name="log">
+ <properties>
+ <help>Option to log packets matching rule</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable log</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable log</description>
+ </valueHelp>
+ <constraint>
+ <regex>(enable|disable)</regex>
+ </constraint>
+ </properties>
+</leafNode>
+<leafNode name="protocol">
+ <properties>
+ <help>Protocol to match (protocol name, number, or "all")</help>
+ <completionHelp>
+ <script>cat /etc/protocols | sed -e '/^#.*/d' | awk '{ print $1 }'</script>
+ </completionHelp>
+ <valueHelp>
+ <format>all</format>
+ <description>All IP protocols</description>
+ </valueHelp>
+ <valueHelp>
+ <format>tcp_udp</format>
+ <description>Both TCP and UDP</description>
+ </valueHelp>
+ <valueHelp>
+ <format>0-255</format>
+ <description>IP protocol number</description>
+ </valueHelp>
+ <valueHelp>
+ <format>!<protocol></format>
+ <description>IP protocol number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ip-protocol"/>
+ </constraint>
+ </properties>
+ <defaultValue>all</defaultValue>
+</leafNode>
+<node name="recent">
+ <properties>
+ <help>Parameters for matching recently seen sources</help>
+ </properties>
+ <children>
+ <leafNode name="count">
+ <properties>
+ <help>Source addresses seen more than N times</help>
+ <valueHelp>
+ <format>u32:1-255</format>
+ <description>Source addresses seen more than N times</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-255"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="time">
+ <properties>
+ <help>Source addresses seen in the last N seconds</help>
+ <valueHelp>
+ <format>u32:0-4294967295</format>
+ <description>Source addresses seen in the last N seconds</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-4294967295"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="set">
+ <properties>
+ <help>Packet modifications</help>
+ </properties>
+ <children>
+ <leafNode name="dscp">
+ <properties>
+ <help>Packet Differentiated Services Codepoint (DSCP)</help>
+ <valueHelp>
+ <format>u32:0-63</format>
+ <description>DSCP number</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 0-63"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="mark">
+ <properties>
+ <help>Packet marking</help>
+ <valueHelp>
+ <format>u32:1-2147483647</format>
+ <description>Packet marking</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-2147483647"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="table">
+ <properties>
+ <help>Routing table to forward packet with</help>
+ <valueHelp>
+ <format>u32:1-200</format>
+ <description>Table number</description>
+ </valueHelp>
+ <valueHelp>
+ <format>main</format>
+ <description>Main table</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 1-200"/>
+ <regex>(main)</regex>
+ </constraint>
+ <completionHelp>
+ <list>main</list>
+ <path>protocols static table</path>
+ </completionHelp>
+ </properties>
+ </leafNode>
+ <leafNode name="tcp-mss">
+ <properties>
+ <help>TCP Maximum Segment Size</help>
+ <valueHelp>
+ <format>u32:500-1460</format>
+ <description>Explicitly set TCP MSS value</description>
+ </valueHelp>
+ <constraint>
+ <validator name="numeric" argument="--range 500-1460"/>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<node name="state">
+ <properties>
+ <help>Session state</help>
+ </properties>
+ <children>
+ <leafNode name="established">
+ <properties>
+ <help>Established state</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable</description>
+ </valueHelp>
+ <constraint>
+ <regex>(enable|disable)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="invalid">
+ <properties>
+ <help>Invalid state</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable</description>
+ </valueHelp>
+ <constraint>
+ <regex>(enable|disable)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="new">
+ <properties>
+ <help>New state</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable</description>
+ </valueHelp>
+ <constraint>
+ <regex>(enable|disable)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ <leafNode name="related">
+ <properties>
+ <help>Related state</help>
+ <completionHelp>
+ <list>enable disable</list>
+ </completionHelp>
+ <valueHelp>
+ <format>enable</format>
+ <description>Enable</description>
+ </valueHelp>
+ <valueHelp>
+ <format>disable</format>
+ <description>Disable</description>
+ </valueHelp>
+ <constraint>
+ <regex>(enable|disable)</regex>
+ </constraint>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+#include <include/firewall/tcp-flags.xml.i>
+<node name="time">
+ <properties>
+ <help>Time to match rule</help>
+ </properties>
+ <children>
+ <leafNode name="monthdays">
+ <properties>
+ <help>Monthdays to match rule on</help>
+ </properties>
+ </leafNode>
+ <leafNode name="startdate">
+ <properties>
+ <help>Date to start matching rule</help>
+ </properties>
+ </leafNode>
+ <leafNode name="starttime">
+ <properties>
+ <help>Time of day to start matching rule</help>
+ </properties>
+ </leafNode>
+ <leafNode name="stopdate">
+ <properties>
+ <help>Date to stop matching rule</help>
+ </properties>
+ </leafNode>
+ <leafNode name="stoptime">
+ <properties>
+ <help>Time of day to stop matching rule</help>
+ </properties>
+ </leafNode>
+ <leafNode name="utc">
+ <properties>
+ <help>Interpret times for startdate, stopdate, starttime and stoptime to be UTC</help>
+ <valueless/>
+ </properties>
+ </leafNode>
+ <leafNode name="weekdays">
+ <properties>
+ <help>Weekdays to match rule on</help>
+ </properties>
+ </leafNode>
+ </children>
+</node>
+<!-- include end -->
diff --git a/interface-definitions/include/policy/route-ipv4.xml.i b/interface-definitions/include/policy/route-ipv4.xml.i new file mode 100644 index 000000000..1f717a1a4 --- /dev/null +++ b/interface-definitions/include/policy/route-ipv4.xml.i @@ -0,0 +1,45 @@ +<!-- include start from policy/route-ipv4.xml.i --> +<node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address.xml.i> + #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/mac-address.xml.i> + #include <include/firewall/port.xml.i> + </children> +</node> +<node name="icmp"> + <properties> + <help>ICMP type and code information</help> + </properties> + <children> + <leafNode name="code"> + <properties> + <help>ICMP code (0-255)</help> + <valueHelp> + <format>u32:0-255</format> + <description>ICMP code (0-255)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + <leafNode name="type"> + <properties> + <help>ICMP type (0-255)</help> + <valueHelp> + <format>u32:0-255</format> + <description>ICMP type (0-255)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + #include <include/firewall/icmp-type-name.xml.i> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/policy/route-ipv6.xml.i b/interface-definitions/include/policy/route-ipv6.xml.i new file mode 100644 index 000000000..d636a654b --- /dev/null +++ b/interface-definitions/include/policy/route-ipv6.xml.i @@ -0,0 +1,196 @@ +<!-- include start from policy/route-ipv6.xml.i --> +<node name="source"> + <properties> + <help>Source parameters</help> + </properties> + <children> + #include <include/firewall/address-ipv6.xml.i> + #include <include/firewall/source-destination-group.xml.i> + #include <include/firewall/mac-address.xml.i> + #include <include/firewall/port.xml.i> + </children> +</node> +<node name="icmpv6"> + <properties> + <help>ICMPv6 type and code information</help> + </properties> + <children> + <leafNode name="type"> + <properties> + <help>ICMP type-name</help> + <completionHelp> + <list>any echo-reply pong destination-unreachable network-unreachable host-unreachable protocol-unreachable port-unreachable fragmentation-needed source-route-failed network-unknown host-unknown network-prohibited host-prohibited TOS-network-unreachable TOS-host-unreachable communication-prohibited host-precedence-violation precedence-cutoff source-quench redirect network-redirect host-redirect TOS-network-redirect TOS host-redirect echo-request ping router-advertisement router-solicitation time-exceeded ttl-exceeded ttl-zero-during-transit ttl-zero-during-reassembly parameter-problem ip-header-bad required-option-missing timestamp-request timestamp-reply address-mask-request address-mask-reply packet-too-big</list> + </completionHelp> + <valueHelp> + <format>any</format> + <description>Any ICMP type/code</description> + </valueHelp> + <valueHelp> + <format>echo-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>pong</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>destination-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>protocol-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>port-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>fragmentation-needed</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>source-route-failed</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-unknown</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-unknown</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-network-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-host-unreachable</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>communication-prohibited</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-precedence-violation</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>precedence-cutoff</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>source-quench</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>network-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>host-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS-network-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>TOS host-redirect</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>echo-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ping</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>router-advertisement</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>router-solicitation</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>time-exceeded</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-exceeded</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-zero-during-transit</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ttl-zero-during-reassembly</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>parameter-problem</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>ip-header-bad</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>required-option-missing</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>timestamp-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>timestamp-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>address-mask-request</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>address-mask-reply</format> + <description>ICMP type/code name</description> + </valueHelp> + <valueHelp> + <format>packet-too-big</format> + <description>ICMP type/code name</description> + </valueHelp> + <constraint> + <regex>(any|echo-reply|pong|destination-unreachable|network-unreachable|host-unreachable|protocol-unreachable|port-unreachable|fragmentation-needed|source-route-failed|network-unknown|host-unknown|network-prohibited|host-prohibited|TOS-network-unreachable|TOS-host-unreachable|communication-prohibited|host-precedence-violation|precedence-cutoff|source-quench|redirect|network-redirect|host-redirect|TOS-network-redirect|TOS host-redirect|echo-request|ping|router-advertisement|router-solicitation|time-exceeded|ttl-exceeded|ttl-zero-during-transit|ttl-zero-during-reassembly|parameter-problem|ip-header-bad|required-option-missing|timestamp-request|timestamp-reply|address-mask-request|address-mask-reply|packet-too-big)</regex> + <validator name="numeric" argument="--range 0-255"/> + </constraint> + </properties> + </leafNode> + </children> +</node> +<!-- include end --> diff --git a/interface-definitions/include/radius-timeout.xml.i b/interface-definitions/include/radius-timeout.xml.i new file mode 100644 index 000000000..22bb6d312 --- /dev/null +++ b/interface-definitions/include/radius-timeout.xml.i @@ -0,0 +1,16 @@ +<!-- include start from radius-timeout.xml.i --> +<leafNode name="timeout"> + <properties> + <help>Session timeout</help> + <valueHelp> + <format>u32:1-240</format> + <description>Session timeout in seconds (default: 2)</description> + </valueHelp> + <constraint> + <validator name="numeric" argument="--range 1-240"/> + </constraint> + <constraintErrorMessage>Timeout must be between 1 and 240 seconds</constraintErrorMessage> + </properties> + <defaultValue>2</defaultValue> +</leafNode> +<!-- include end --> diff --git a/interface-definitions/interfaces-bridge.xml.in b/interface-definitions/interfaces-bridge.xml.in index 1e11cd4c6..d633077d9 100644 --- a/interface-definitions/interfaces-bridge.xml.in +++ b/interface-definitions/interfaces-bridge.xml.in @@ -151,7 +151,7 @@ <description>VLAN id range allowed on this interface (use '-' as delimiter)</description> </valueHelp> <constraint> - <validator name="allowed-vlan"/> + <validator name="numeric" argument="--allow-range --range 1-4094"/> </constraint> <constraintErrorMessage>not a valid VLAN ID value or range</constraintErrorMessage> <multi/> diff --git a/interface-definitions/policy-route.xml.in b/interface-definitions/policy-route.xml.in index f480f3bd5..44b96c2e6 100644 --- a/interface-definitions/policy-route.xml.in +++ b/interface-definitions/policy-route.xml.in @@ -46,7 +46,8 @@ #include <include/firewall/port.xml.i> </children> </node> - #include <include/policy/route-common-rule-ipv6.xml.i> + #include <include/policy/route-common.xml.i> + #include <include/policy/route-ipv6.xml.i> #include <include/firewall/dscp.xml.i> #include <include/firewall/packet-length.xml.i> #include <include/firewall/hop-limit.xml.i> @@ -98,7 +99,8 @@ #include <include/firewall/port.xml.i> </children> </node> - #include <include/policy/route-common-rule.xml.i> + #include <include/policy/route-common.xml.i> + #include <include/policy/route-ipv4.xml.i> #include <include/firewall/dscp.xml.i> #include <include/firewall/packet-length.xml.i> #include <include/firewall/ttl.xml.i> diff --git a/interface-definitions/system-login.xml.in b/interface-definitions/system-login.xml.in index def42544a..027d3f587 100644 --- a/interface-definitions/system-login.xml.in +++ b/interface-definitions/system-login.xml.in @@ -127,32 +127,44 @@ </leafNode> <leafNode name="type"> <properties> - <help>Public key type</help> + <help>SSH public key type</help> <completionHelp> - <list>ssh-dss ssh-rsa ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 ssh-ed25519</list> + <list>ssh-dss ssh-rsa ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521 ssh-ed25519 ecdsa-sk ed25519-sk</list> </completionHelp> <valueHelp> <format>ssh-dss</format> - <description/> + <description>Digital Signature Algorithm (DSA) key support</description> </valueHelp> <valueHelp> <format>ssh-rsa</format> - <description/> + <description>Key pair based on RSA algorithm</description> </valueHelp> <valueHelp> <format>ecdsa-sha2-nistp256</format> - <description/> + <description>Elliptic Curve DSA with NIST P-256 curve</description> </valueHelp> <valueHelp> <format>ecdsa-sha2-nistp384</format> - <description/> + <description>Elliptic Curve DSA with NIST P-384 curve</description> + </valueHelp> + <valueHelp> + <format>ecdsa-sha2-nistp521</format> + <description>Elliptic Curve DSA with NIST P-521 curve</description> </valueHelp> <valueHelp> <format>ssh-ed25519</format> - <description/> + <description>Edwards-curve DSA with elliptic curve 25519</description> + </valueHelp> + <valueHelp> + <format>ecdsa-sk</format> + <description>Elliptic Curve DSA security key</description> + </valueHelp> + <valueHelp> + <format>ed25519-sk</format> + <description>Elliptic curve 25519 security key</description> </valueHelp> <constraint> - <regex>(ssh-dss|ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519)</regex> + <regex>(ssh-dss|ssh-rsa|ecdsa-sha2-nistp256|ecdsa-sha2-nistp384|ecdsa-sha2-nistp521|ssh-ed25519|ecdsa-sk|ed25519-sk)</regex> </constraint> </properties> </leafNode> diff --git a/interface-definitions/vpn-ipsec.xml.in b/interface-definitions/vpn-ipsec.xml.in index 4776c53dc..64966b540 100644 --- a/interface-definitions/vpn-ipsec.xml.in +++ b/interface-definitions/vpn-ipsec.xml.in @@ -888,6 +888,7 @@ <node name="radius"> <children> #include <include/radius-nas-identifier.xml.i> + #include <include/radius-timeout.xml.i> <tagNode name="server"> <children> #include <include/accel-ppp/radius-additions-disable-accounting.xml.i> diff --git a/interface-definitions/vpn-openconnect.xml.in b/interface-definitions/vpn-openconnect.xml.in index 3b3a83bd4..8b60f2e6e 100644 --- a/interface-definitions/vpn-openconnect.xml.in +++ b/interface-definitions/vpn-openconnect.xml.in @@ -140,20 +140,7 @@ #include <include/radius-server-ipv4.xml.i> <node name="radius"> <children> - <leafNode name="timeout"> - <properties> - <help>Session timeout</help> - <valueHelp> - <format>u32:1-240</format> - <description>Session timeout in seconds (default: 2)</description> - </valueHelp> - <constraint> - <validator name="numeric" argument="--range 1-240"/> - </constraint> - <constraintErrorMessage>Timeout must be between 1 and 240 seconds</constraintErrorMessage> - </properties> - <defaultValue>2</defaultValue> - </leafNode> + #include <include/radius-timeout.xml.i> <leafNode name="groupconfig"> <properties> <help>If the groupconfig option is set, then config-per-user will be overriden, and all configuration will be read from RADIUS.</help> diff --git a/op-mode-definitions/dhcp.xml.in b/op-mode-definitions/dhcp.xml.in index 241cca0ce..ce4026ff4 100644 --- a/op-mode-definitions/dhcp.xml.in +++ b/op-mode-definitions/dhcp.xml.in @@ -16,7 +16,7 @@ <properties> <help>Show DHCP server leases</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/show_dhcp.py --leases</command> + <command>sudo ${vyos_op_scripts_dir}/dhcp.py show_server_leases --family inet</command> <children> <tagNode name="pool"> <properties> @@ -82,7 +82,7 @@ <properties> <help>Show DHCPv6 server leases</help> </properties> - <command>sudo ${vyos_op_scripts_dir}/show_dhcpv6.py --leases</command> + <command>sudo ${vyos_op_scripts_dir}/dhcp.py show_server_leases --family inet6</command> <children> <tagNode name="pool"> <properties> diff --git a/python/vyos/opmode.py b/python/vyos/opmode.py index 727e118a8..2e896c8e6 100644 --- a/python/vyos/opmode.py +++ b/python/vyos/opmode.py @@ -16,6 +16,7 @@ import re import sys import typing +from humps import decamelize class Error(Exception): @@ -200,6 +201,7 @@ def run(module): if not args["raw"]: return res else: + res = decamelize(res) res = _normalize_field_names(res) from json import dumps return dumps(res, indent=4) diff --git a/src/conf_mode/vpn_ipsec.py b/src/conf_mode/vpn_ipsec.py index 77a425f8b..cfefcfbe8 100755 --- a/src/conf_mode/vpn_ipsec.py +++ b/src/conf_mode/vpn_ipsec.py @@ -117,13 +117,26 @@ def get_config(config=None): ipsec['ike_group'][group]['proposal'][proposal] = dict_merge(default_values, ipsec['ike_group'][group]['proposal'][proposal]) - if 'remote_access' in ipsec and 'connection' in ipsec['remote_access']: + # XXX: T2665: we can not safely rely on the defaults() when there are + # tagNodes in place, it is better to blend in the defaults manually. + if dict_search('remote_access.connection', ipsec): default_values = defaults(base + ['remote-access', 'connection']) for rw in ipsec['remote_access']['connection']: ipsec['remote_access']['connection'][rw] = dict_merge(default_values, ipsec['remote_access']['connection'][rw]) - if 'remote_access' in ipsec and 'radius' in ipsec['remote_access'] and 'server' in ipsec['remote_access']['radius']: + # XXX: T2665: we can not safely rely on the defaults() when there are + # tagNodes in place, it is better to blend in the defaults manually. + if dict_search('remote_access.radius.server', ipsec): + # Fist handle the "base" stuff like RADIUS timeout + default_values = defaults(base + ['remote-access', 'radius']) + if 'server' in default_values: + del default_values['server'] + ipsec['remote_access']['radius'] = dict_merge(default_values, + ipsec['remote_access']['radius']) + + # Take care about individual RADIUS servers implemented as tagNodes - this + # requires special treatment default_values = defaults(base + ['remote-access', 'radius', 'server']) for server in ipsec['remote_access']['radius']['server']: ipsec['remote_access']['radius']['server'][server] = dict_merge(default_values, diff --git a/src/op_mode/bgp.py b/src/op_mode/bgp.py new file mode 100755 index 000000000..23001a9d7 --- /dev/null +++ b/src/op_mode/bgp.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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/>. +# +# Purpose: +# Displays bgp neighbors information. +# Used by the "show bgp (vrf <tag>) ipv4|ipv6 neighbors" commands. + +import re +import sys +import typing + +import jmespath +from jinja2 import Template +from humps import decamelize + +from vyos.configquery import ConfigTreeQuery + +import vyos.opmode + + +frr_command_template = Template(""" +{% if family %} + show bgp + {{ 'vrf ' ~ vrf if vrf else '' }} + {{ 'ipv6' if family == 'inet6' else 'ipv4'}} + {{ 'neighbor ' ~ peer if peer else 'summary' }} +{% endif %} + +{% if raw %} + json +{% endif %} +""") + + +def _verify(func): + """Decorator checks if BGP config exists + BGP configuration can be present under vrf <tag> + If we do npt get arg 'peer' then it can be 'bgp summary' + """ + from functools import wraps + + @wraps(func) + def _wrapper(*args, **kwargs): + config = ConfigTreeQuery() + afi = 'ipv6' if kwargs.get('family') == 'inet6' else 'ipv4' + global_vrfs = ['all', 'default'] + peer = kwargs.get('peer') + vrf = kwargs.get('vrf') + unconf_message = f'BGP or neighbor is not configured' + # Add option to check the specific neighbor if we have arg 'peer' + peer_opt = f'neighbor {peer} address-family {afi}-unicast' if peer else '' + vrf_opt = '' + if vrf and vrf not in global_vrfs: + vrf_opt = f'vrf name {vrf}' + # Check if config does not exist + if not config.exists(f'{vrf_opt} protocols bgp {peer_opt}'): + raise vyos.opmode.UnconfiguredSubsystem(unconf_message) + return func(*args, **kwargs) + + return _wrapper + + +@_verify +def show_neighbors(raw: bool, + family: str, + peer: typing.Optional[str], + vrf: typing.Optional[str]): + kwargs = dict(locals()) + frr_command = frr_command_template.render(kwargs) + frr_command = re.sub(r'\s+', ' ', frr_command) + + from vyos.util import cmd + output = cmd(f"vtysh -c '{frr_command}'") + + if raw: + from json import loads + data = loads(output) + # Get list of the peers + peers = jmespath.search('*.peers | [0]', data) + if peers: + # Create new dict, delete old key 'peers' + # add key 'peers' neighbors to the list + list_peers = [] + new_dict = jmespath.search('* | [0]', data) + if 'peers' in new_dict: + new_dict.pop('peers') + + for neighbor, neighbor_options in peers.items(): + neighbor_options['neighbor'] = neighbor + list_peers.append(neighbor_options) + new_dict['peers'] = list_peers + return decamelize(new_dict) + data = jmespath.search('* | [0]', data) + return decamelize(data) + + else: + return output + + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) diff --git a/src/op_mode/dhcp.py b/src/op_mode/dhcp.py new file mode 100755 index 000000000..07e9b7d6c --- /dev/null +++ b/src/op_mode/dhcp.py @@ -0,0 +1,278 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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/>. + +import sys +from ipaddress import ip_address +import typing + +from datetime import datetime +from sys import exit +from tabulate import tabulate +from isc_dhcp_leases import IscDhcpLeases + +from vyos.base import Warning +from vyos.configquery import ConfigTreeQuery + +from vyos.util import cmd +from vyos.util import dict_search +from vyos.util import is_systemd_service_running + +import vyos.opmode + + +config = ConfigTreeQuery() +pool_key = "shared-networkname" + + +def _in_pool(lease, pool): + if pool_key in lease.sets: + if lease.sets[pool_key] == pool: + return True + return False + + +def _utc_to_local(utc_dt): + return datetime.fromtimestamp((datetime.fromtimestamp(utc_dt) - datetime(1970, 1, 1)).total_seconds()) + + +def _format_hex_string(in_str): + out_str = "" + # if input is divisible by 2, add : every 2 chars + if len(in_str) > 0 and len(in_str) % 2 == 0: + out_str = ':'.join(a+b for a,b in zip(in_str[::2], in_str[1::2])) + else: + out_str = in_str + + return out_str + + +def _find_list_of_dict_index(lst, key='ip', value='') -> int: + """ + Find the index entry of list of dict matching the dict value + Exampe: + % lst = [{'ip': '192.0.2.1'}, {'ip': '192.0.2.2'}] + % _find_list_of_dict_index(lst, key='ip', value='192.0.2.2') + % 1 + """ + idx = next((index for (index, d) in enumerate(lst) if d[key] == value), None) + return idx + + +def _get_raw_server_leases(family, pool=None) -> list: + """ + Get DHCP server leases + :return list + """ + lease_file = '/config/dhcpdv6.leases' if family == 'inet6' else '/config/dhcpd.leases' + data = [] + leases = IscDhcpLeases(lease_file).get() + if pool is not None: + if config.exists(f'service dhcp-server shared-network-name {pool}'): + leases = list(filter(lambda x: _in_pool(x, pool), leases)) + for lease in leases: + data_lease = {} + data_lease['ip'] = lease.ip + data_lease['state'] = lease.binding_state + data_lease['pool'] = lease.sets.get('shared-networkname', '') + data_lease['end'] = lease.end.timestamp() + + if family == 'inet': + data_lease['hardware'] = lease.ethernet + data_lease['start'] = lease.start.timestamp() + data_lease['hostname'] = lease.hostname + + if family == 'inet6': + data_lease['last_communication'] = lease.last_communication.timestamp() + data_lease['iaid_duid'] = _format_hex_string(lease.host_identifier_string) + lease_types_long = {'na': 'non-temporary', 'ta': 'temporary', 'pd': 'prefix delegation'} + data_lease['type'] = lease_types_long[lease.type] + + data_lease['remaining'] = lease.end - datetime.utcnow() + + if data_lease['remaining'].days >= 0: + # substraction gives us a timedelta object which can't be formatted with strftime + # so we use str(), split gets rid of the microseconds + data_lease['remaining'] = str(data_lease["remaining"]).split('.')[0] + else: + data_lease['remaining'] = '' + + # Do not add old leases + if data_lease['remaining'] != '': + data.append(data_lease) + + # deduplicate + checked = [] + for entry in data: + addr = entry.get('ip') + if addr not in checked: + checked.append(addr) + else: + idx = _find_list_of_dict_index(data, key='ip', value=addr) + data.pop(idx) + + return data + + +def _get_formatted_server_leases(raw_data, family): + data_entries = [] + if family == 'inet': + for lease in raw_data: + ipaddr = lease.get('ip') + hw_addr = lease.get('hardware') + state = lease.get('state') + start = lease.get('start') + start = _utc_to_local(start).strftime('%Y/%m/%d %H:%M:%S') + end = lease.get('end') + end = _utc_to_local(end).strftime('%Y/%m/%d %H:%M:%S') + remain = lease.get('remaining') + pool = lease.get('pool') + hostname = lease.get('hostname') + data_entries.append([ipaddr, hw_addr, state, start, end, remain, pool, hostname]) + + headers = ['IP Address', 'Hardware address', 'State', 'Lease start', 'Lease expiration', 'Remaining', 'Pool', + 'Hostname'] + + if family == 'inet6': + for lease in raw_data: + ipaddr = lease.get('ip') + state = lease.get('state') + start = lease.get('last_communication') + start = _utc_to_local(start).strftime('%Y/%m/%d %H:%M:%S') + end = lease.get('end') + end = _utc_to_local(end).strftime('%Y/%m/%d %H:%M:%S') + remain = lease.get('remaining') + lease_type = lease.get('type') + pool = lease.get('pool') + host_identifier = lease.get('iaid_duid') + data_entries.append([ipaddr, state, start, end, remain, lease_type, pool, host_identifier]) + + headers = ['IPv6 address', 'State', 'Last communication', 'Lease expiration', 'Remaining', 'Type', 'Pool', + 'IAID_DUID'] + + output = tabulate(data_entries, headers, numalign='left') + return output + + +def _get_dhcp_pools(family='inet') -> list: + v = 'v6' if family == 'inet6' else '' + pools = config.list_nodes(f'service dhcp{v}-server shared-network-name') + return pools + + +def _get_pool_size(pool, family='inet'): + v = 'v6' if family == 'inet6' else '' + base = f'service dhcp{v}-server shared-network-name {pool}' + size = 0 + subnets = config.list_nodes(f'{base} subnet') + for subnet in subnets: + if family == 'inet6': + ranges = config.list_nodes(f'{base} subnet {subnet} address-range start') + else: + ranges = config.list_nodes(f'{base} subnet {subnet} range') + for range in ranges: + if family == 'inet6': + start = config.list_nodes(f'{base} subnet {subnet} address-range start')[0] + stop = config.value(f'{base} subnet {subnet} address-range start {start} stop') + else: + start = config.value(f'{base} subnet {subnet} range {range} start') + stop = config.value(f'{base} subnet {subnet} range {range} stop') + # Add +1 because both range boundaries are inclusive + size += int(ip_address(stop)) - int(ip_address(start)) + 1 + return size + + +def _get_raw_pool_statistics(family='inet', pool=None): + if pool is None: + pool = _get_dhcp_pools(family=family) + else: + pool = [pool] + + v = 'v6' if family == 'inet6' else '' + stats = [] + for p in pool: + subnet = config.list_nodes(f'service dhcp{v}-server shared-network-name {p} subnet') + size = _get_pool_size(family=family, pool=p) + leases = len(_get_raw_server_leases(family=family, pool=p)) + use_percentage = round(leases / size * 100) if size != 0 else 0 + pool_stats = {'pool': p, 'size': size, 'leases': leases, + 'available': (size - leases), 'use_percentage': use_percentage, 'subnet': subnet} + stats.append(pool_stats) + return stats + + +def _get_formatted_pool_statistics(pool_data, family='inet'): + data_entries = [] + for entry in pool_data: + pool = entry.get('pool') + size = entry.get('size') + leases = entry.get('leases') + available = entry.get('available') + use_percentage = entry.get('use_percentage') + use_percentage = f'{use_percentage}%' + data_entries.append([pool, size, leases, available, use_percentage]) + + headers = ['Pool', 'Size','Leases', 'Available', 'Usage'] + output = tabulate(data_entries, headers, numalign='left') + return output + + +def _verify(func): + """Decorator checks if DHCP(v6) config exists""" + from functools import wraps + + @wraps(func) + def _wrapper(*args, **kwargs): + config = ConfigTreeQuery() + family = kwargs.get('family') + v = 'v6' if family == 'inet6' else '' + unconf_message = f'DHCP{v} server is not configured' + # Check if config does not exist + if not config.exists(f'service dhcp{v}-server'): + raise vyos.opmode.UnconfiguredSubsystem(unconf_message) + return func(*args, **kwargs) + return _wrapper + + +@_verify +def show_pool_statistics(raw: bool, family: str, pool: typing.Optional[str]): + pool_data = _get_raw_pool_statistics(family=family, pool=pool) + if raw: + return pool_data + else: + return _get_formatted_pool_statistics(pool_data, family=family) + + +@_verify +def show_server_leases(raw: bool, family: str): + # if dhcp server is down, inactive leases may still be shown as active, so warn the user. + if not is_systemd_service_running('isc-dhcp-server.service'): + Warning('DHCP server is configured but not started. Data may be stale.') + + leases = _get_raw_server_leases(family) + if raw: + return leases + else: + return _get_formatted_server_leases(leases, family) + + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) diff --git a/src/op_mode/log.py b/src/op_mode/log.py new file mode 100755 index 000000000..b0abd6191 --- /dev/null +++ b/src/op_mode/log.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2022 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# 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/>. + +import json +import re +import sys +import typing + +from jinja2 import Template + +from vyos.util import rc_cmd + +import vyos.opmode + +journalctl_command_template = Template(""" +--no-hostname +--quiet + +{% if boot %} + --boot +{% endif %} + +{% if count %} + --lines={{ count }} +{% endif %} + +{% if reverse %} + --reverse +{% endif %} + +{% if since %} + --since={{ since }} +{% endif %} + +{% if unit %} + --unit={{ unit }} +{% endif %} + +{% if utc %} + --utc +{% endif %} + +{% if raw %} +{# By default show 100 only lines for raw option if count does not set #} +{# Protection from parsing the full log by default #} +{% if not boot %} + --lines={{ '' ~ count if count else '100' }} +{% endif %} + --no-pager + --output=json +{% endif %} +""") + + +def show(raw: bool, + boot: typing.Optional[bool], + count: typing.Optional[int], + facility: typing.Optional[str], + reverse: typing.Optional[bool], + utc: typing.Optional[bool], + unit: typing.Optional[str]): + kwargs = dict(locals()) + + journalctl_options = journalctl_command_template.render(kwargs) + journalctl_options = re.sub(r'\s+', ' ', journalctl_options) + rc, output = rc_cmd(f'journalctl {journalctl_options}') + if raw: + # Each 'journalctl --output json' line is a separate JSON object + # So we should return list of dict + return [json.loads(line) for line in output.split('\n')] + return output + + +if __name__ == '__main__': + try: + res = vyos.opmode.run(sys.modules[__name__]) + if res: + print(res) + except (ValueError, vyos.opmode.Error) as e: + print(e) + sys.exit(1) diff --git a/src/op_mode/ping.py b/src/op_mode/ping.py index 60bbc0c78..5e5b95a0a 100755 --- a/src/op_mode/ping.py +++ b/src/op_mode/ping.py @@ -18,6 +18,32 @@ import os import sys import socket import ipaddress +import json +from vyos.util import cmd, rc_cmd +from vyos.ifconfig import Section + + +def interface_list() -> list: + """ + Get list of interfaces in system + :rtype: list + """ + return Section.interfaces() + + +def vrf_list() -> list: + """ + Get list of VRFs in system + :rtype: list + """ + result = cmd(f'sudo ip --json --brief link show type vrf') + data = json.loads(result) + vrflist: list = [] + for o in data: + if 'ifname' in o: + vrflist.append(o['ifname']) + return vrflist + options = { 'audible': { @@ -63,6 +89,7 @@ options = { 'interface': { 'ping': '{command} -I {value}', 'type': '<interface>', + 'helpfunction': interface_list, 'help': 'Source interface' }, 'interval': { @@ -128,6 +155,7 @@ options = { 'ping': 'sudo ip vrf exec {value} {command}', 'type': '<vrf>', 'help': 'Use specified VRF table', + 'helpfunction': vrf_list, 'dflt': 'default', }, 'verbose': { @@ -142,20 +170,33 @@ ping = { } -class List (list): - def first (self): +class List(list): + def first(self): return self.pop(0) if self else '' def last(self): return self.pop() if self else '' - def prepend(self,value): - self.insert(0,value) + def prepend(self, value): + self.insert(0, value) + + +def completion_failure(option: str) -> None: + """ + Shows failure message after TAB when option is wrong + :param option: failure option + :type str: + """ + sys.stderr.write('\n\n Invalid option: {}\n\n'.format(option)) + sys.stdout.write('<nocomps>') + sys.exit(1) def expension_failure(option, completions): reason = 'Ambiguous' if completions else 'Invalid' - sys.stderr.write('\n\n {} command: {} [{}]\n\n'.format(reason,' '.join(sys.argv), option)) + sys.stderr.write( + '\n\n {} command: {} [{}]\n\n'.format(reason, ' '.join(sys.argv), + option)) if completions: sys.stderr.write(' Possible completions:\n ') sys.stderr.write('\n '.join(completions)) @@ -196,28 +237,44 @@ if __name__ == '__main__': if host == '--get-options': args.first() # pop ping args.first() # pop IP + usedoptionslist = [] while args: - option = args.first() - - matched = complete(option) + option = args.first() # pop option + matched = complete(option) # get option parameters + usedoptionslist.append(option) # list of used options + # Select options if not args: + # remove from Possible completions used options + for o in usedoptionslist: + if o in matched: + matched.remove(o) sys.stdout.write(' '.join(matched)) sys.exit(0) - if len(matched) > 1 : + if len(matched) > 1: sys.stdout.write(' '.join(matched)) sys.exit(0) + # If option doesn't have value + if matched: + if options[matched[0]]['type'] == 'noarg': + continue + else: + # Unexpected option + completion_failure(option) - if options[matched[0]]['type'] == 'noarg': - continue - - value = args.first() + value = args.first() # pop option's value if not args: matched = complete(option) - sys.stdout.write(options[matched[0]]['type']) + helplines = options[matched[0]]['type'] + # Run helpfunction to get list of possible values + if 'helpfunction' in options[matched[0]]: + result = options[matched[0]]['helpfunction']() + if result: + helplines = '\n' + ' '.join(result) + sys.stdout.write(helplines) sys.exit(0) - for name,option in options.items(): + for name, option in options.items(): if 'dflt' in option and name not in args: args.append(name) args.append(option['dflt']) @@ -234,8 +291,7 @@ if __name__ == '__main__': except ValueError: sys.exit(f'ping: Unknown host: {host}') - command = convert(ping[version],args) + command = convert(ping[version], args) # print(f'{command} {host}') os.system(f'{command} {host}') - diff --git a/src/services/api/graphql/libs/op_mode.py b/src/services/api/graphql/libs/op_mode.py index da2bcdb5b..97a26520e 100644 --- a/src/services/api/graphql/libs/op_mode.py +++ b/src/services/api/graphql/libs/op_mode.py @@ -17,8 +17,11 @@ import os import re import typing import importlib.util +from typing import Union +from humps import decamelize from vyos.defaults import directories +from vyos.opmode import _normalize_field_names def load_as_module(name: str, path: str): spec = importlib.util.spec_from_file_location(name, path) @@ -98,3 +101,6 @@ def map_type_name(type_name: type, optional: bool = False) -> str: # scalar 'Generic' is defined in schema.graphql return 'Generic' + +def normalize_output(result: Union[dict, list]) -> Union[dict, list]: + return _normalize_field_names(decamelize(result)) diff --git a/src/services/api/graphql/session/session.py b/src/services/api/graphql/session/session.py index c2c1db1df..0b77b1433 100644 --- a/src/services/api/graphql/session/session.py +++ b/src/services/api/graphql/session/session.py @@ -25,6 +25,7 @@ from vyos.template import render from vyos.opmode import Error as OpModeError from api.graphql.libs.op_mode import load_op_mode_as_module, split_compound_op_mode_name +from api.graphql.libs.op_mode import normalize_output op_mode_include_file = os.path.join(directories['data'], 'op-mode-standardized.json') @@ -149,6 +150,8 @@ class Session: except OpModeError as e: raise e + res = normalize_output(res) + return res def gen_op_mutation(self): diff --git a/src/system/keepalived-fifo.py b/src/system/keepalived-fifo.py index a0fccd1d0..864ee8419 100755 --- a/src/system/keepalived-fifo.py +++ b/src/system/keepalived-fifo.py @@ -67,13 +67,13 @@ class KeepalivedFifo: # For VRRP configuration to be read, the commit must be finished count = 1 while commit_in_progress(): - if ( count <= 40 ): - logger.debug(f'commit in progress try: {count}') + if ( count <= 20 ): + logger.debug(f'Attempt to load keepalived configuration aborted due to a commit in progress (attempt {count}/20)') else: - logger.error(f'commit still in progress after {count} continuing anyway') + logger.error(f'Forced keepalived configuration loading despite a commit in progress ({count} wait time expired, not waiting further)') break count += 1 - time.sleep(0.5) + time.sleep(1) try: base = ['high-availability', 'vrrp'] diff --git a/src/validators/allowed-vlan b/src/validators/allowed-vlan deleted file mode 100755 index 11389390b..000000000 --- a/src/validators/allowed-vlan +++ /dev/null @@ -1,19 +0,0 @@ -#! /usr/bin/python3 - -import sys -import re - -if __name__ == '__main__': - if len(sys.argv)>1: - allowed_vlan = sys.argv[1] - if re.search('[0-9]{1,4}-[0-9]{1,4}', allowed_vlan): - for tmp in allowed_vlan.split('-'): - if int(tmp) not in range(1, 4095): - sys.exit(1) - else: - if int(allowed_vlan) not in range(1, 4095): - sys.exit(1) - else: - sys.exit(2) - - sys.exit(0) diff --git a/src/validators/dotted-decimal b/src/validators/dotted-decimal deleted file mode 100755 index 652110346..000000000 --- a/src/validators/dotted-decimal +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# 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/>. - -import re -import sys - -area = sys.argv[1] - -res = re.match(r'^(\d+)\.(\d+)\.(\d+)\.(\d+)$', area) -if not res: - print("\'{0}\' is not a valid dotted decimal value".format(area)) - sys.exit(1) -else: - components = res.groups() - for n in range(0, 4): - if (int(components[n]) > 255): - print("Invalid component of a dotted decimal value: {0} exceeds 255".format(components[n])) - sys.exit(1) - -sys.exit(0) diff --git a/src/validators/fqdn b/src/validators/fqdn index a4027e4ca..a65d2d5d4 100755 --- a/src/validators/fqdn +++ b/src/validators/fqdn @@ -1,27 +1,2 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2020-2021 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# 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/>. - -import re -import sys - -pattern = '[A-Za-z0-9][-.A-Za-z0-9]*' - -if __name__ == '__main__': - if len(sys.argv) != 2: - sys.exit(1) - if not re.match(pattern, sys.argv[1]): - sys.exit(1) - sys.exit(0) +#!/usr/bin/env sh +${vyos_libexec_dir}/validate-value --regex "[A-Za-z0-9][-.A-Za-z0-9]*" --value "$1" diff --git a/src/validators/mac-address b/src/validators/mac-address index 7d020f387..bb859a603 100755 --- a/src/validators/mac-address +++ b/src/validators/mac-address @@ -1,27 +1,2 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2018-2020 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# 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/>. - -import re -import sys - -pattern = "^([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" - -if __name__ == '__main__': - if len(sys.argv) != 2: - sys.exit(1) - if not re.match(pattern, sys.argv[1]): - sys.exit(1) - sys.exit(0) +#!/usr/bin/env sh +${vyos_libexec_dir}/validate-value --regex "([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})" --value "$1" diff --git a/src/validators/mac-address-exclude b/src/validators/mac-address-exclude new file mode 100755 index 000000000..c44913023 --- /dev/null +++ b/src/validators/mac-address-exclude @@ -0,0 +1,2 @@ +#!/usr/bin/env sh +${vyos_libexec_dir}/validate-value --regex "!([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})" --value "$1" diff --git a/src/validators/mac-address-firewall b/src/validators/mac-address-firewall deleted file mode 100755 index 70551f86d..000000000 --- a/src/validators/mac-address-firewall +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python3 -# -# Copyright (C) 2018-2022 VyOS maintainers and contributors -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 or later as -# published by the Free Software Foundation. -# -# 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/>. - -import re -import sys - -pattern = "^!?([0-9A-Fa-f]{2}:){5}([0-9A-Fa-f]{2})$" - -if __name__ == '__main__': - if len(sys.argv) != 2: - sys.exit(1) - if not re.match(pattern, sys.argv[1]): - sys.exit(1) - sys.exit(0) diff --git a/src/validators/tcp-flag b/src/validators/tcp-flag deleted file mode 100755 index 1496b904a..000000000 --- a/src/validators/tcp-flag +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/python3 - -import sys -import re - -if __name__ == '__main__': - if len(sys.argv)>1: - flag = sys.argv[1] - if flag and flag[0] == '!': - flag = flag[1:] - if flag not in ['syn', 'ack', 'rst', 'fin', 'urg', 'psh', 'ecn', 'cwr']: - print(f'Error: {flag} is not a valid TCP flag') - sys.exit(1) - else: - sys.exit(2) - - sys.exit(0) |