From 286caf891727f360230d6bd6045eceddc19ad21f Mon Sep 17 00:00:00 2001 From: Daniel Steglich Date: Sun, 9 Aug 2015 22:48:17 +0200 Subject: [PATCH] Added a new network connection type to handle PPPoE connections * Added a new choice to main selectbox for adding Network Connections (network.py) * Added a new form which asks for name, interface, firewall zone, username and password (forms.py, urls.py) * Added new helper functions to create PPPoE based connection object (network.py) --- plinth/modules/networks/forms.py | 23 +++++++++++ plinth/modules/networks/networks.py | 48 +++++++++++++++++++++- plinth/modules/networks/urls.py | 1 + plinth/network.py | 63 ++++++++++++++++++++++++++++- 4 files changed, 131 insertions(+), 4 deletions(-) diff --git a/plinth/modules/networks/forms.py b/plinth/modules/networks/forms.py index ba0b52281..32166bfeb 100644 --- a/plinth/modules/networks/forms.py +++ b/plinth/modules/networks/forms.py @@ -73,6 +73,29 @@ available over this interfaces. Select Internal only for trusted networks.'), self.fields['interface'].choices = choices +class AddPPPoEForm(forms.Form): + """Form to create a new pppoe connection.""" + name = forms.CharField(label=_('Connection Name')) + interface = forms.ChoiceField( + label=_('Physical Interface'), + choices=(), + help_text=_('The network device that this connection should be bound ' + 'to.')) + zone = forms.ChoiceField( + label=_('Firewall Zone'), + help_text=_('The firewall zone will control which services are \ +available over this interfaces. Select Internal only for trusted networks.'), + choices=[('external', 'External'), ('internal', 'Internal')]) + username = forms.CharField(label=_('Username')) + password = forms.CharField(label=_('Password')) + + def __init__(self, *args, **kwargs): + """Initialize the form, populate interface choices.""" + super(AddPPPoEForm, self).__init__(*args, **kwargs) + choices = _get_interface_choices(nm.DeviceType.ETHERNET) + self.fields['interface'].choices = choices + + class AddWifiForm(forms.Form): """Form to create a new wifi connection.""" name = forms.CharField(label=_('Connection Name')) diff --git a/plinth/modules/networks/networks.py b/plinth/modules/networks/networks.py index c4e5991fb..a7e7cd029 100644 --- a/plinth/modules/networks/networks.py +++ b/plinth/modules/networks/networks.py @@ -23,6 +23,7 @@ from gettext import gettext as _ from logging import Logger from .forms import ConnectionTypeSelectForm, AddEthernetForm, AddWifiForm +from .forms import AddPPPoEForm from plinth import cfg from plinth import network from plinth import package @@ -70,8 +71,10 @@ def edit(request, uuid): if request.method == 'POST': if connection.get_connection_type() == '802-11-wireless': form = AddWifiForm(request.POST) - else: + elif connection.get_connection_type() == '802-3-ethernet': form = AddEthernetForm(request.POST) + elif connection.get_connection_type() == 'pppoe': + form = AddPPPoEForm(request.POST) if form.is_valid(): name = form.cleaned_data['name'] @@ -79,6 +82,8 @@ def edit(request, uuid): zone = form.cleaned_data['zone'] ipv4_method = form.cleaned_data['ipv4_method'] ipv4_address = form.cleaned_data['ipv4_address'] + username = form.cleaned_data['username'] + password = form.cleaned_data['password'] if connection.get_connection_type() == '802-3-ethernet': network.edit_ethernet_connection( @@ -93,6 +98,9 @@ def edit(request, uuid): network.edit_wifi_connection( connection, name, interface, zone, ssid, mode, auth_mode, passphrase, ipv4_method, ipv4_address) + elif connection.get_connection_type() == 'pppoe': + network.edit_pppoe_connection( + connection, name, interface, zone, username, password) return redirect(reverse_lazy('networks:index')) else: @@ -103,6 +111,7 @@ def edit(request, uuid): else: settings_connection = connection.get_setting_connection() settings_ipv4 = connection.get_setting_ip4_config() + settings_pppoe = connection.get_setting_pppoe() form_data['interface'] = connection.get_interface_name() try: form_data['zone'] = settings_connection.get_zone() @@ -110,6 +119,12 @@ def edit(request, uuid): form_data['zone'] = 'external' form_data['ipv4_method'] = settings_ipv4.get_method() + if not settings_pppoe: + form_data['username'] = '' + form_data['password'] = '' + else: + form_data['username'] = settings_pppoe.get_username() + form_data['password'] = settings_pppoe.get_password() if settings_ipv4.get_num_addresses(): # XXX: Plinth crashes here. Possibly because a double free bug @@ -136,8 +151,10 @@ def edit(request, uuid): form_data['auth_mode'] = 'open' form = AddWifiForm(form_data) - else: + elif settings_connection.get_connection_type() == '802-3-ethernet': form = AddEthernetForm(form_data) + elif settings_connection.get_connection_type() == 'pppoe': + form = AddPPPoEForm(form_data) return TemplateResponse(request, 'connections_edit.html', {'title': _('Edit Connection'), @@ -196,6 +213,8 @@ def add(request): return redirect(reverse_lazy('networks:add_ethernet')) elif connection_type == '802-11-wireless': return redirect(reverse_lazy('networks:add_wifi')) + elif connection_type == 'pppoe': + return redirect(reverse_lazy('networks:add_pppoe')) else: form = ConnectionTypeSelectForm() return TemplateResponse(request, 'connections_type_select.html', @@ -229,6 +248,31 @@ def add_ethernet(request): 'form': form}) +def add_pppoe(request): + """Serve pppoe connection create form.""" + form = None + + if request.method == 'POST': + form = AddPPPoEForm(request.POST) + if form.is_valid(): + name = form.cleaned_data['name'] + interface = form.cleaned_data['interface'] + zone = form.cleaned_data['zone'] + username = form.cleaned_data['username'] + password = form.cleaned_data['password'] + + network.add_pppoe_connection( + name, interface, zone, username, password) + return redirect(reverse_lazy('networks:index')) + else: + form = AddPPPoEForm() + + return TemplateResponse(request, 'connections_create.html', + {'title': _('Adding New PPPoE Connection'), + 'subsubmenu': subsubmenu, + 'form': form}) + + def add_wifi(request, ssid=None): """Serve wifi connection create form.""" form = None diff --git a/plinth/modules/networks/urls.py b/plinth/modules/networks/urls.py index 9ced17d2b..cfd3a4c97 100644 --- a/plinth/modules/networks/urls.py +++ b/plinth/modules/networks/urls.py @@ -34,6 +34,7 @@ urlpatterns = patterns( url(r'^sys/networks/scan/$', 'scan', name='scan'), url(r'^sys/networks/add/$', 'add', name='add'), url(r'^sys/networks/add/ethernet/$', 'add_ethernet', name='add_ethernet'), + url(r'^sys/networks/add/pppoe/$', 'add_pppoe', name='add_pppoe'), url(r'^sys/networks/add/wifi/(?:(?P[^/]+)/)?$', 'add_wifi', name='add_wifi'), url(r'^sys/networks/(?P[\w.@+-]+)/delete/$', diff --git a/plinth/network.py b/plinth/network.py index d788b56ff..afbca76ed 100644 --- a/plinth/network.py +++ b/plinth/network.py @@ -32,6 +32,7 @@ logger = logging.getLogger(__name__) CONNECTION_TYPE_NAMES = { '802-3-ethernet': 'Ethernet', '802-11-wireless': 'Wi-Fi', + 'pppoe': 'PPPoE', } @@ -127,8 +128,8 @@ def get_active_connection(connection_uuid): raise ConnectionNotFound(connection_uuid) -def _update_common_settings(connection, connection_uuid, name, type_, interface, - zone, ipv4_method, ipv4_address): +def _update_common_settings(connection, connection_uuid, name, type_, + interface, zone, ipv4_method, ipv4_address): """Create/edit basic settings for network manager connections.""" if not connection: connection = nm.SimpleConnection.new() @@ -184,6 +185,59 @@ def _update_ethernet_settings(connection, connection_uuid, name, interface, return connection +def _update_pppoe_settings(connection, connection_uuid, name, interface, zone, + username, password): + """Create/edit ethernet settings for network manager connections.""" + type_ = 'pppoe' + + connection = _update_common_settings(connection, connection_uuid, name, + type_, interface, zone, 'auto', + '0.0.0.0') + + #pppoe + settings = connection.get_setting_pppoe() + if not settings: + settings = nm.SettingPppoe.new() + + settings.set_property(nm.SETTING_PPPOE_USERNAME, username) + settings.set_property(nm.SETTING_PPPOE_PASSWORD, password) + connection.add_setting(settings) + + settings = connection.get_setting_ppp() + if not settings: + settings = nm.SettingPpp.new() + + #ToDo: make this configurable? + #ToDo: apt-get install ppp pppoe + settings.set_property(nm.SETTING_PPP_LCP_ECHO_FAILURE, 5) + settings.set_property(nm.SETTING_PPP_LCP_ECHO_INTERVAL, 30) + + connection.add_setting(settings) + return connection + + +def add_pppoe_connection(name, interface, zone, username, password): + """Add an automatic pppoe connection in network manager. + + Return the UUID for the connection. + """ + connection_uuid = str(uuid.uuid4()) + connection = _update_pppoe_settings( + None, connection_uuid, name, interface, zone, username, password) + client = nm.Client.new(None) + client.add_connection_async(connection, True, None, _callback, None) + return connection_uuid + + +def edit_pppoe_connection(connection, name, interface, zone, username, + password): + """Edit an existing pppoe connection in network manager.""" + _update_pppoe_settings( + connection, connection.get_uuid(), name, interface, zone, username, + password) + connection.commit_changes(True) + + def add_ethernet_connection(name, interface, zone, ipv4_method, ipv4_address): """Add an automatic ethernet connection in network manager. @@ -272,6 +326,11 @@ def activate_connection(connection_uuid): # Find the connection connection = get_connection(connection_uuid) + # ToDo: is the following code still needed? Because the connections + # are bound to an interface and for this reason, the device name should + # be available within connection object. So simply use: + # connection.get_interface_name() ?? + # Find a suitable device client = nm.Client.new(None) connection_type = connection.get_connection_type()