summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Jenkinsfile14
-rw-r--r--interface-definitions/system-syslog.xml.in14
-rw-r--r--op-mode-definitions/traceroute.xml46
-rw-r--r--python/vyos/ifconfig/interface.py6
-rw-r--r--python/vyos/ifconfig/vxlan.py29
-rw-r--r--python/vyos/ifconfig/wireguard.py3
-rwxr-xr-xscripts/build-command-templates5
-rwxr-xr-xsrc/conf_mode/interfaces-l2tpv3.py35
-rwxr-xr-xsrc/conf_mode/ntp.py3
-rwxr-xr-xsrc/validators/fqdn27
10 files changed, 117 insertions, 65 deletions
diff --git a/Jenkinsfile b/Jenkinsfile
index ed98477f2..7a79b0f43 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -36,7 +36,7 @@ def isCustomBuild() {
def gitURI = 'git@github.com:vyos/' + getGitRepoName()
def httpURI = 'https://github.com/vyos/' + getGitRepoName()
- return ! ((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI))
+ return !((getGitRepoURL() == gitURI) || (getGitRepoURL() == httpURI)) || env.CHANGE_ID
}
def setDescription() {
@@ -74,7 +74,13 @@ node('Docker') {
script {
// create container name on demand
def branchName = getGitBranchName()
- if (branchName == "master") {
+ // Adjust PR target branch name so we can re-map it to the proper
+ // Docker image. CHANGE_ID is set only for pull requests, so it is
+ // safe to access the pullRequest global variable
+ if (env.CHANGE_ID) {
+ branchName = "${env.CHANGE_TARGET}".toLowerCase()
+ }
+ if (branchName.equals("master")) {
branchName = "current"
}
env.DOCKER_IMAGE = "vyos/vyos-build:" + branchName
@@ -92,7 +98,6 @@ pipeline {
}
options {
disableConcurrentBuilds()
- skipDefaultCheckout()
timeout(time: 30, unit: 'MINUTES')
timestamps()
}
@@ -101,8 +106,7 @@ pipeline {
steps {
script {
dir('build') {
- git branch: getGitBranchName(),
- url: getGitRepoURL()
+ checkout scm
}
}
}
diff --git a/interface-definitions/system-syslog.xml.in b/interface-definitions/system-syslog.xml.in
index 2079ec0ea..194cdb851 100644
--- a/interface-definitions/system-syslog.xml.in
+++ b/interface-definitions/system-syslog.xml.in
@@ -181,13 +181,17 @@
<properties>
<help>Logging to a remote host</help>
<constraint>
- <validator name="ip-address" />
- <regex>(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)</regex>
+ <validator name="ip-address"/>
+ <validator name="fqdn"/>
</constraint>
- <constraintErrorMessage>Invalid host FQDN or IP address</constraintErrorMessage>
+ <constraintErrorMessage>Invalid host (FQDN or IP address)</constraintErrorMessage>
<valueHelp>
- <format>x.x.x.x or host.domain.tld</format>
- <description>Remote host name or IP address</description>
+ <format>ipv4</format>
+ <description>Remote syslog server IPv4 address</description>
+ </valueHelp>
+ <valueHelp>
+ <format>hostname</format>
+ <description>Remote syslog server FQDN</description>
</valueHelp>
</properties>
<children>
diff --git a/op-mode-definitions/traceroute.xml b/op-mode-definitions/traceroute.xml
index 85f6047c1..d16e9e3b8 100644
--- a/op-mode-definitions/traceroute.xml
+++ b/op-mode-definitions/traceroute.xml
@@ -12,9 +12,8 @@
<list>&lt;hostname&gt; &lt;x.x.x.x&gt; &lt;h:h:h:h:h:h:h:h&gt;</list>
</completionHelp>
</properties>
- <command>/usr/bin/traceroute $2</command>
+ <command>traceroute $2</command>
</tagNode>
-
<tagNode name="ipv4">
<properties>
<help>Track network path to &lt;hostname|IPv4 address&gt;</help>
@@ -22,9 +21,8 @@
<list>&lt;hostname&gt; &lt;x.x.x.x&gt;</list>
</completionHelp>
</properties>
- <command>/usr/bin/traceroute -4 $3</command>
+ <command>traceroute -4 $3</command>
</tagNode>
-
<tagNode name="ipv6">
<properties>
<help>Track network path to &lt;hostname|IPv6 address&gt;</help>
@@ -32,11 +30,47 @@
<list>&lt;hostname&gt; &lt;h:h:h:h:h:h:h:h&gt;</list>
</completionHelp>
</properties>
- <command>/usr/bin/traceroute -6 $3</command>
+ <command>traceroute -6 $3</command>
+ </tagNode>
+ <tagNode name="vrf">
+ <properties>
+ <help>Track network path to specified node via given VRF instance</help>
+ <completionHelp>
+ <path>vrf name</path>
+ </completionHelp>
+ </properties>
+ <children>
+ <tagNode name="">
+ <properties>
+ <help>Track network path to specified node</help>
+ <completionHelp>
+ <list>&lt;hostname&gt; &lt;x.x.x.x&gt; &lt;h:h:h:h:h:h:h:h&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ip vrf exec "$3" traceroute "$4"</command>
+ </tagNode>
+ <tagNode name="ipv4">
+ <properties>
+ <help>Track network path to &lt;hostname|IPv4 address&gt;</help>
+ <completionHelp>
+ <list>&lt;hostname&gt; &lt;x.x.x.x&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ip vrf exec "$3" traceroute -4 "$5"</command>
+ </tagNode>
+ <tagNode name="ipv6">
+ <properties>
+ <help>Track network path to &lt;hostname|IPv6 address&gt;</help>
+ <completionHelp>
+ <list>&lt;hostname&gt; &lt;h:h:h:h:h:h:h:h&gt;</list>
+ </completionHelp>
+ </properties>
+ <command>sudo ip vrf exec "$3" traceroute -6 "$5"</command>
+ </tagNode>
+ </children>
</tagNode>
</children>
</node>
-
<node name="monitor">
<children>
<tagNode name="traceroute">
diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py
index a750bda3f..b002e0171 100644
--- a/python/vyos/ifconfig/interface.py
+++ b/python/vyos/ifconfig/interface.py
@@ -741,12 +741,6 @@ class Interface(Control):
with open(self._dhcpv6_cfg_file, 'w') as f:
f.write(dhcpv6_text)
- # https://bugs.launchpad.net/ubuntu/+source/ifupdown/+bug/1447715
- #
- # wee need to wait for IPv6 DAD to finish once and interface is added
- # this suxx :-(
- sleep(5)
-
# no longer accept router announcements on this interface
self._write_sysfs('/proc/sys/net/ipv6/conf/{}/accept_ra'
.format(self.config['ifname']), 0)
diff --git a/python/vyos/ifconfig/vxlan.py b/python/vyos/ifconfig/vxlan.py
index bc2ec508b..86702b2cd 100644
--- a/python/vyos/ifconfig/vxlan.py
+++ b/python/vyos/ifconfig/vxlan.py
@@ -13,7 +13,7 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <http://www.gnu.org/licenses/>.
-
+from vyos import ConfigError
from vyos.ifconfig.interface import Interface
@@ -54,20 +54,23 @@ class VXLANIf(Interface):
super().__init__(ifname, **kargs)
def _create(self):
- # we assume that by default a multicast interface is created
- group = 'group {}'.format(self.config['group'])
-
- # if remote host is specified we ignore the multicast address
+ cmd = ''
if self.config['remote']:
- group = 'remote {}'.format(self.config['remote'])
-
- # an underlay device is not always specified
- dev = ''
- if self.config['dev']:
- dev = 'dev {}'.format(self.config['dev'])
+ # an underlay device is only mandatory with multicast, not unicast
+ dev = ''
+ if self.config['dev']:
+ dev = 'dev {}'.format(self.config['dev'])
+ # iproute2 command for unicast
+ cmd = 'ip link add {ifname} type vxlan id {vni} remote {remote} {dev_optional} dstport {port}'.format(
+ **self.config, dev_optional=dev)
+ else:
+ if not self.config['dev']:
+ raise ConfigError(
+ f'VXLAN "{self.config["ifname"]}" is missing mandatory underlay interface for a multicast network.')
+ # iproute2 command for multicast
+ cmd = 'ip link add {ifname} type vxlan id {vni} group {group} dev {dev} dstport {port}'.format(
+ **self.config)
- cmd = 'ip link add {ifname} type vxlan id {vni} {group} {dev} dstport {port}'.format(
- **config)
self._cmd(cmd)
@staticmethod
diff --git a/python/vyos/ifconfig/wireguard.py b/python/vyos/ifconfig/wireguard.py
index 2926e72e1..411c3e146 100644
--- a/python/vyos/ifconfig/wireguard.py
+++ b/python/vyos/ifconfig/wireguard.py
@@ -16,6 +16,7 @@
import os
+import vyos
from vyos.ifconfig.interface import Interface
class WireGuardIf(Interface):
@@ -101,7 +102,7 @@ class WireGuardIf(Interface):
wgdump = vyos.interfaces.wireguard_dump().get(
self.config['ifname'], None)
- c = Config()
+ c = vyos.config.Config()
c.set_level(["interfaces", "wireguard", self.config['ifname']])
description = c.return_effective_value(["description"])
ips = c.return_effective_values(["address"])
diff --git a/scripts/build-command-templates b/scripts/build-command-templates
index dbf4ad9c5..c6534a6d8 100755
--- a/scripts/build-command-templates
+++ b/scripts/build-command-templates
@@ -264,6 +264,11 @@ def process_node(n, tmpl_dir):
if node_type == "tagNode":
props["tag"] = "True"
+ if node_type != "leafNode":
+ if "multi" in props:
+ raise ValueError("<multi/> tag is only allowed in <leafNode>")
+ if "valueless" in props:
+ raise ValueError("<valueless/> is only allowed in <leafNode>")
nodedef_path = os.path.join(make_path(my_tmpl_dir), "node.def")
if not os.path.exists(nodedef_path):
diff --git a/src/conf_mode/interfaces-l2tpv3.py b/src/conf_mode/interfaces-l2tpv3.py
index 1b9425f64..3bc3faca8 100755
--- a/src/conf_mode/interfaces-l2tpv3.py
+++ b/src/conf_mode/interfaces-l2tpv3.py
@@ -42,6 +42,13 @@ default_config_data = {
'tunnel_id': ''
}
+def check_kmod():
+ modules = ['l2tp_eth', 'l2tp_netlink', 'l2tp_ip', 'l2tp_ip6']
+ for module in modules:
+ if not os.path.exists(f'/sys/module/{module}'):
+ if os.system(f'modprobe {module}') != 0:
+ raise ConfigError(f'Loading Kernel module {module} failed')
+
def get_config():
l2tpv3 = deepcopy(default_config_data)
conf = Config()
@@ -152,35 +159,8 @@ def verify(l2tpv3):
def generate(l2tpv3):
- if l2tpv3['deleted']:
- # bail out early
- return None
-
- # initialize kernel module if not loaded
- if not os.path.isdir('/sys/module/l2tp_eth'):
- if os.system('modprobe l2tp_eth') != 0:
- raise ConfigError("failed loading l2tp_eth kernel module")
-
- if not os.path.isdir('/sys/module/l2tp_netlink'):
- if os.system('modprobe l2tp_netlink') != 0:
- raise ConfigError("failed loading l2tp_netlink kernel module")
-
- if not os.path.isdir('/sys/module/l2tp_ip'):
- if os.system('modprobe l2tp_ip') != 0:
- raise ConfigError("failed loading l2tp_ip kernel module")
-
- if l2tpv3['encapsulation'] == 'ip':
- if not os.path.isdir('/sys/module/l2tp_ip'):
- if os.system('modprobe l2tp_ip') != 0:
- raise ConfigError("failed loading l2tp_ip kernel module")
-
- if not os.path.isdir('/sys/module/l2tp_ip6 '):
- if os.system('modprobe l2tp_ip6 ') != 0:
- raise ConfigError("failed loading l2tp_ip6 kernel module")
-
return None
-
def apply(l2tpv3):
# L2TPv3 interface needs to be created/deleted on-block, instead of
# passing a ton of arguments, I just use a dict that is managed by
@@ -230,6 +210,7 @@ def apply(l2tpv3):
if __name__ == '__main__':
try:
+ check_kmod()
c = get_config()
verify(c)
generate(c)
diff --git a/src/conf_mode/ntp.py b/src/conf_mode/ntp.py
index 8f32e6e81..f706d502f 100755
--- a/src/conf_mode/ntp.py
+++ b/src/conf_mode/ntp.py
@@ -42,8 +42,6 @@ restrict default noquery nopeer notrap nomodify
restrict 127.0.0.1
restrict -6 ::1
-# Do not listen on any interface address by default
-interface ignore wildcard
#
# Configurable section
#
@@ -65,6 +63,7 @@ restrict {{ n.address }} mask {{ n.netmask }} nomodify notrap nopeer
{% if listen_address -%}
# NTP should listen on configured addresses only
+interface ignore wildcard
{% for a in listen_address -%}
interface listen {{ a }}
{% endfor -%}
diff --git a/src/validators/fqdn b/src/validators/fqdn
new file mode 100755
index 000000000..9f4ed764f
--- /dev/null
+++ b/src/validators/fqdn
@@ -0,0 +1,27 @@
+#!/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/>.
+
+from re import match
+from sys import argv,exit
+
+if len(argv) == 2:
+ # pattern copied from: https://www.regextester.com/103452
+ pattern = "(?=^.{4,253}$)(^((?!-)[a-zA-Z0-9-]{0,62}[a-zA-Z0-9]\.)+[a-zA-Z]{2,63}$)"
+ if match(pattern, argv[1]):
+ exit(0)
+ else:
+ exit(1)
+