Page MenuHomeVyOS Platform

interfaces-pppoe.py
No OneTemporary

Size
8 KB
Referenced Files
None
Subscribers
None

interfaces-pppoe.py

#!/usr/bin/env python3
#
# Copyright (C) 2019 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 os
from sys import exit
from copy import deepcopy
from jinja2 import Template
from psutil import pid_exists
from stat import S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IXGRP, S_IROTH, S_IXOTH
from subprocess import Popen, PIPE
from vyos.config import Config
from vyos import ConfigError
from netifaces import interfaces
# Please be careful if you edit the template.
config_pppoe_tmpl = """
### Autogenerated by interfaces-pppoe.py ###
# Configuration file for PPP, using PPP over Ethernet (PPPOE)
# to connect to a DSL provider.
# Default parameters not set by Vyatta templates:
#
# Require peer to provide the local IP address if it is not
# specified explicitly in the config file.
noipdefault
# Don't show the password in logfiles:
hide-password
# Standard Link Control Protocol (LCP) parameters:
lcp-echo-interval 20
lcp-echo-failure 3
# RFC 2516, paragraph 7 mandates that the following options MUST NOT be
# requested and MUST be rejected if requested by the peer:
# Address-and-Control-Field-Compression (ACFC)
noaccomp
# Asynchronous-Control-Character-Map (ACCM)
default-asyncmap
# Override any connect script that may have been set in /etc/ppp/options.
connect /bin/true
# Don't try to authenticate the remote node
noauth
# Don't try to proxy ARP for the remote endpoint. User can set proxy
# arp entries up manually if they wish. More importantly, having
# the "proxyarp" parameter set disables the "defaultroute" option.
noproxyarp
plugin rp-pppoe.so
{{ link }}
persist
ifname {{ intf }}
ipparam {{ intf }}
debug
logfile /var/log/vyatta/ppp_{{ intf }}.log
{% if 'auto' in default_route -%}
defaultroute
{% elif 'force' in default_route -%}
defaultroute
replacedefaultroute
{% endif %}
mtu {{ mtu }}
mru {{ mtu }}
user "{{ user_id }}"
password "{{ password }}"
{% if 'auto' in name_server -%}
usepeerdns
{% endif %}
{% if ipv6_enable -%}
+ipv6
{% endif %}
"""
config_pppoe_autoconf_tmpl = """
#!/bin/sh
if [ "$6" != "{{ intf }}" ]; then
exit
fi
echo 0 > /proc/sys/net/ipv6/conf/$1/forwarding
echo 2 > /proc/sys/net/ipv6/conf/$1/accept_ra
echo 1 > /proc/sys/net/ipv6/conf/$1/autoconf
"""
default_config_data = {
'access_concentrator': '',
'on_demand': False,
'default_route': 'auto',
'deleted': False,
'disable': False,
'intf': '',
'idle_timeout': '',
'ipv6_autoconf': False,
'ipv6_enable': False,
'link': '',
'local_address': '',
'mtu': '1492',
'name_server': 'auto',
'password': '',
'remote_address': '',
'service_name': '',
'user_id': ''
}
def subprocess_cmd(command):
print(command)
p = Popen(command, stdout=PIPE, shell=True)
p.communicate()
def get_config():
pppoe = deepcopy(default_config_data)
conf = Config()
# determine tagNode instance
try:
pppoe['intf'] = os.environ['VYOS_TAGNODE_VALUE']
except KeyError as E:
print("Interface not specified")
# Check if interface has been removed
if not conf.exists('interfaces pppoe ' + pppoe['intf']):
pppoe['deleted'] = True
return pppoe
# set new configuration level
conf.set_level('interfaces pppoe ' + pppoe['intf'])
# Access concentrator name (only connect to this concentrator)
if conf.exists('access-concentrator'):
pppoe['access_concentrator'] = conf.return_values('access-concentrator')
# Access concentrator name (only connect to this concentrator)
if conf.exists('connect-on-demand'):
pppoe['on_demand'] = True
# Enable/Disable default route to peer when link comes up
if conf.exists('default-route'):
pppoe['default_route'] = conf.return_value('default-route')
# Disable this interface
if conf.exists('disable'):
pppoe['disable'] = True
# Delay before disconnecting idle session (in seconds)
if conf.exists('idle-timeout'):
pppoe['idle_timeout'] = conf.return_value('idle-timeout')
# Enable Stateless Address Autoconfiguration (SLAAC)
if conf.exists('ipv6 address autoconf'):
pppoe['ipv6_autoconf'] = True
# Activate IPv6 support on this connection
if conf.exists('ipv6 enable'):
pppoe['ipv6_enable'] = True
# IPv4 address of local end of the PPPoE link
if conf.exists('local-address'):
pppoe['local_address'] = conf.return_value('local-address')
# Physical Interface used for this PPPoE session
if conf.exists('link'):
pppoe['link'] = conf.return_value('link')
# Maximum Transmission Unit (MTU)
if conf.exists('mtu'):
pppoe['mtu'] = conf.return_value('mtu')
# IPv4 address of local end of the PPPoE link
if conf.exists('name-server'):
pppoe['name_server'] = conf.return_value('name-server')
# Password for authenticating local machine to PPPoE server
if conf.exists('password'):
pppoe['password'] = conf.return_value('password')
# IPv4 address of local end of the PPPoE link
if conf.exists('remote-address'):
pppoe['remote_address'] = conf.return_value('remote-address')
# Service name, only connect to access concentrators advertising this
if conf.exists('service-name'):
pppoe['service_name'] = conf.return_value('service-name')
# Authentication name supplied to PPPoE server
if conf.exists('user-id'):
pppoe['user_id'] = conf.return_value('user-id')
return pppoe
def verify(pppoe):
if pppoe['deleted']:
# bail out early
return None
if not pppoe['link']:
raise ConfigError('Physical link interface for PPPoE missing')
return None
def generate(pppoe):
config_file_pppoe = '/etc/ppp/peers/{}'.format(pppoe['intf'])
config_file_ifup = '/etc/ppp/ipv6-up.d/50-vyos-{}-autoconf'.format(pppoe['intf'])
pid = 0
pidfile = '/var/run/{}.pid'.format(pppoe['intf'])
if os.path.isfile(pidfile):
pid = 0
with open(pidfile, 'r') as f:
pid = int(f.read())
# Always stop OpenVPN service. We can not send a SIGUSR1 for restart of the
# service as the configuration is not re-read. Stop daemon only if it's
# running - it could have died or killed by someone evil
print("pid: {}".format(pid))
if pid_exists(pid):
cmd = 'start-stop-daemon --stop --quiet'
cmd += ' --pidfile ' + pidfile
subprocess_cmd(cmd)
if pppoe['deleted']:
# Delete PPP configuration files
if os.path.exists(config_file_pppoe):
os.unlink(config_file_pppoe)
if os.path.exists(config_file_ifup):
os.unlink(config_file_ifup)
else:
# Create PPP configuration files
tmpl = Template(config_pppoe_tmpl)
config_text = tmpl.render(pppoe)
with open(config_file_pppoe, 'w') as f:
f.write(config_text)
tmpl = Template(config_pppoe_autoconf_tmpl)
config_text = tmpl.render(pppoe)
with open(config_file_ifup, 'w') as f:
f.write(config_text)
os.chmod(config_file_ifup,
S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
if not pppoe['disable']:
# No matching PPP process running - spawn a new one
cmd = 'start-stop-daemon --start --quiet'
cmd += ' --pidfile ' + pidfile
cmd += ' --background'
cmd += ' --exec /usr/sbin/pppd'
# now pass arguments to pppd binary
cmd += ' -- '
cmd += ' call {}'.format(pppoe['intf'])
# execute assembled command
subprocess_cmd(cmd)
return None
def apply(pppoe):
return None
if __name__ == '__main__':
try:
c = get_config()
verify(c)
generate(c)
apply(c)
except ConfigError as e:
print(e)
exit(1)

File Metadata

Mime Type
text/x-script.python
Expires
Sat, Oct 17, 12:54 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4350091
Default Alt Text
interfaces-pppoe.py (8 KB)

Event Timeline