From 4a8a3e1325bcfe4f6fcbb328cdd1eb67b3b0d86a Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Wed, 4 Mar 2020 08:55:53 +0100
Subject: pppoe: T1318: IPv6 support

---
 src/conf_mode/interfaces-pppoe.py | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index 8ec78bab3..90d34fa4a 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -23,6 +23,7 @@ from subprocess import Popen, PIPE
 from time import sleep
 from pwd import getpwnam
 from grp import getgrnam
+from stat import S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IXGRP, S_IROTH, S_IXOTH
 
 from vyos.config import Config
 from vyos.ifconfig import Interface
@@ -99,6 +100,21 @@ rp_pppoe_service "{{ service_name }}"
 
 """
 
+config_pppoe_ipv6_up_tmpl = """
+#!/bin/sh
+
+logger -t PPPoE/{{ intf }} "1:$1 2:$2 3:$3 4:$4 5:$5 6:$6 "
+
+if [ "$6" != "{{ intf }}" ]; then
+    exit
+fi
+
+echo 0 > /proc/sys/net/ipv6/conf/{{ intf }}/forwarding
+echo 2 > /proc/sys/net/ipv6/conf/{{ intf }}/accept_ra
+echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/autoconf
+
+"""
+
 PPP_LOGFILE = '/var/log/vyatta/ppp_{}.log'
 
 default_config_data = {
@@ -228,6 +244,7 @@ def verify(pppoe):
 
 def generate(pppoe):
     config_file_pppoe = '/etc/ppp/peers/{}'.format(pppoe['intf'])
+    script_file = '/etc/ppp/ipv6-up.d/50-vyos-{}-autoconf'.format(pppoe['intf'])
 
     # Always hang-up PPPoE connection prior generating new configuration file
     cmd = 'systemctl stop ppp@{}.service'.format(pppoe['intf'])
@@ -238,6 +255,9 @@ def generate(pppoe):
         if os.path.exists(config_file_pppoe):
             os.unlink(config_file_pppoe)
 
+        if os.path.exists(script_file)
+            os.unlink(config_file_pppoe)
+
     else:
         # Create PPP configuration files
         tmpl = Template(config_pppoe_tmpl)
@@ -245,6 +265,15 @@ def generate(pppoe):
         with open(config_file_pppoe, 'w') as f:
             f.write(config_text)
 
+        if pppoe['ipv6_enable']:
+            script_file = '/etc/ppp/ipv6-up.d/50-vyos-{}-autoconf'.format(pppoe['intf'])
+            tmpl = Template(config_pppoe_ipv6_up_tmpl)
+            config_text = tmpl.render(pppoe)
+            with open(script_file, 'w') as f:
+                f.write(config_text)
+
+            os.chmod(script_file, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+
     return None
 
 def apply(pppoe):
-- 
cgit v1.2.3


From d860d2f136e92c2bb959ad3c6dd9db70da0480b6 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Thu, 5 Mar 2020 17:20:30 +0100
Subject: vxlan: T1636: ensure 'link' interface really exists

---
 src/conf_mode/interfaces-vxlan.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py
index dabfe4836..c9ef0fe9c 100755
--- a/src/conf_mode/interfaces-vxlan.py
+++ b/src/conf_mode/interfaces-vxlan.py
@@ -134,8 +134,11 @@ def verify(vxlan):
     if vxlan['mtu'] < 1500:
         print('WARNING: RFC7348 recommends VXLAN tunnels preserve a 1500 byte MTU')
 
-    if vxlan['group'] and not vxlan['link']:
-        raise ConfigError('Multicast VXLAN requires an underlaying interface ')
+    if vxlan['group']:
+        if not vxlan['link']:
+            raise ConfigError('Multicast VXLAN requires an underlaying interface ')
+        if not vxlan['link'] in interfaces():
+            raise ConfigError('VXLAN source interface does not exist')
 
     if not (vxlan['group'] or vxlan['remote']):
         raise ConfigError('Group or remote must be configured')
-- 
cgit v1.2.3


From 4affc8b2fde2f0883632f163db5961ae34faccc4 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Thu, 5 Mar 2020 17:20:55 +0100
Subject: macvlan: T1635: ensure 'link' interface really exists

---
 src/conf_mode/interfaces-pseudo-ethernet.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/conf_mode/interfaces-pseudo-ethernet.py b/src/conf_mode/interfaces-pseudo-ethernet.py
index 3d36da226..09d580b28 100755
--- a/src/conf_mode/interfaces-pseudo-ethernet.py
+++ b/src/conf_mode/interfaces-pseudo-ethernet.py
@@ -196,6 +196,9 @@ def verify(peth):
     if not peth['link']:
         raise ConfigError('Link device must be set for virtual ethernet {}'.format(peth['intf']))
 
+    if not peth['link'] in interfaces():
+        raise ConfigError('Pseudo-ethernet source interface does not exist')
+
     return None
 
 def generate(peth):
-- 
cgit v1.2.3


From 2242f7d8abcafcd1c1f33ad6b59e2b22979adb69 Mon Sep 17 00:00:00 2001
From: Christian Poessinger <christian@poessinger.com>
Date: Thu, 5 Mar 2020 17:22:19 +0100
Subject: pppoe: T1493: support IPv6 address negotiation which is required for
 DHCPv6-PD

---
 src/conf_mode/interfaces-pppoe.py | 88 +++++++++++++++++++++++----------------
 1 file changed, 51 insertions(+), 37 deletions(-)

diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py
index 90d34fa4a..0622e4c9a 100755
--- a/src/conf_mode/interfaces-pppoe.py
+++ b/src/conf_mode/interfaces-pppoe.py
@@ -31,9 +31,7 @@ from vyos import ConfigError
 from netifaces import interfaces
 
 # Please be careful if you edit the template.
-config_pppoe_tmpl = """
-### Autogenerated by interfaces-pppoe.py ###
-
+config_pppoe_tmpl = """### Autogenerated by interfaces-pppoe.py ###
 {% if description %}
 # {{ description }}
 {% endif %}
@@ -93,6 +91,7 @@ usepeerdns
 {% endif %}
 {% if ipv6_enable -%}
 +ipv6
+ipv6cp-use-ipaddr
 {% endif %}
 {% if service_name -%}
 rp_pppoe_service "{{ service_name }}"
@@ -100,19 +99,53 @@ rp_pppoe_service "{{ service_name }}"
 
 """
 
-config_pppoe_ipv6_up_tmpl = """
-#!/bin/sh
+# Please be careful if you edit the template.
+# There must be no blank line at the top pf the script file
+config_pppoe_ipv6_up_tmpl = """#!/bin/sh
 
-logger -t PPPoE/{{ intf }} "1:$1 2:$2 3:$3 4:$4 5:$5 6:$6 "
+# As PPPoE is an "on demand" interface we need to re-configure it when it
+# becomes up
 
 if [ "$6" != "{{ intf }}" ]; then
     exit
 fi
 
-echo 0 > /proc/sys/net/ipv6/conf/{{ intf }}/forwarding
+# add some info to syslog
+DIALER_PID=$(cat /var/run/{{ intf }}.pid)
+logger -t pppd[$DIALER_PID] "executing $0"
+logger -t pppd[$DIALER_PID] "configuring dialer interface $6 via $2"
+
+echo "{{ description }}" > /sys/class/net/{{ intf }}/ifalias
+
+{% if ipv6_autoconf -%}
+
+
+# Configure interface-specific Host/Router behaviour.
+# Note: It is recommended to have the same setting on all interfaces; mixed
+# router/host scenarios are rather uncommon. Possible values are:
+#
+# 0  Forwarding disabled
+# 1  Forwarding enabled
+#
+echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/forwarding
+
+# Accept Router Advertisements; autoconfigure using them.
+#
+# It also determines whether or not to transmit Router
+# Solicitations. If and only if the functional setting is to
+# accept Router Advertisements, Router Solicitations will be
+# transmitted. Possible values are:
+#
+# 0  Do not accept Router Advertisements.
+# 1  Accept Router Advertisements if forwarding is disabled.
+# 2  Overrule forwarding behaviour. Accept Router Advertisements
+#    even if forwarding is enabled.
+#
 echo 2 > /proc/sys/net/ipv6/conf/{{ intf }}/accept_ra
-echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/autoconf
 
+# Autoconfigure addresses using Prefix Information in Router Advertisements.
+echo 1 > /proc/sys/net/ipv6/conf/{{ intf }}/autoconfigure
+{% endif %}
 """
 
 PPP_LOGFILE = '/var/log/vyatta/ppp_{}.log'
@@ -124,7 +157,7 @@ default_config_data = {
     'on_demand': False,
     'default_route': 'auto',
     'deleted': False,
-    'description': '',
+    'description': '\0',
     'disable': False,
     'intf': '',
     'idle_timeout': '',
@@ -235,9 +268,9 @@ def verify(pppoe):
         return None
 
     if not pppoe['source_interface']:
-        raise ConfigError('PPPoE source interface is missing')
+        raise ConfigError('PPPoE source interface missing')
 
-    if pppoe['source_interface'] not in interfaces():
+    if not pppoe['source_interface'] in interfaces():
         raise ConfigError('PPPoE source interface does not exist')
 
     return None
@@ -255,7 +288,7 @@ def generate(pppoe):
         if os.path.exists(config_file_pppoe):
             os.unlink(config_file_pppoe)
 
-        if os.path.exists(script_file)
+        if os.path.exists(script_file):
             os.unlink(config_file_pppoe)
 
     else:
@@ -265,14 +298,13 @@ def generate(pppoe):
         with open(config_file_pppoe, 'w') as f:
             f.write(config_text)
 
-        if pppoe['ipv6_enable']:
-            script_file = '/etc/ppp/ipv6-up.d/50-vyos-{}-autoconf'.format(pppoe['intf'])
-            tmpl = Template(config_pppoe_ipv6_up_tmpl)
-            config_text = tmpl.render(pppoe)
-            with open(script_file, 'w') as f:
-                f.write(config_text)
+        script_file = '/etc/ppp/ipv6-up.d/50-vyos-{}-autoconf'.format(pppoe['intf'])
+        tmpl = Template(config_pppoe_ipv6_up_tmpl)
+        config_text = tmpl.render(pppoe)
+        with open(script_file, 'w') as f:
+            f.write(config_text)
 
-            os.chmod(script_file, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
+        os.chmod(script_file, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
 
     return None
 
@@ -292,24 +324,6 @@ def apply(pppoe):
             gid = getgrnam('vyattacfg').gr_gid
             os.chown(pppoe['logfile'], uid, gid)
 
-    # better late then sorry ... but we can only set interface alias after
-    # pppd has been launched and created the interface
-    cnt = 0
-    while pppoe['intf'] not in interfaces():
-        cnt += 1
-        if cnt == 50:
-            break
-
-        # sleep 250ms
-        sleep(0.250)
-
-    try:
-        # we need to catch the exception if the interface is not up due to
-        # reason stated above
-        Interface(pppoe['intf']).set_alias(pppoe['description'])
-    except:
-        pass
-
     return None
 
 if __name__ == '__main__':
-- 
cgit v1.2.3