diff --git a/setup.py b/setup.py index ab8c9cc..f69e01a 100755 --- a/setup.py +++ b/setup.py @@ -10,7 +10,7 @@ from DistUtilsExtra.command.build_i18n import build_i18n from DistUtilsExtra.command.clean_i18n import clean_i18n -__VERSION__ = '6.7' +__VERSION__ = '6.8' PROGRAM_VERSION = __VERSION__ prefix = '/usr/local' if system() == 'FreeBSD' else sys.prefix diff --git a/src/auto-switch.py b/src/auto-switch.py index 16dfa32..cc0ad04 100755 --- a/src/auto-switch.py +++ b/src/auto-switch.py @@ -1,36 +1,34 @@ #!/usr/local/bin/python3 """ -auto-switch - is used to automatically switches the default interface go down. +auto-switch - is used to automatically switch the default interface go down. """ import sys -import os import re -from subprocess import Popen, PIPE +from subprocess import run, PIPE args = sys.argv if len(args) != 2: exit() nic = args[1] -not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|wlan" \ - r"ppp|bridge|wg)[0-9]+(\s*)|vm-[a-z]+(\s*)" +not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ + r"ppp|bridge|wg)[0-9]|vm-[a-z]" -default_nic = Popen( +default_nic = run( 'netstat -rn | grep default', stdout=PIPE, shell=True, universal_newlines=True -).stdout.read() +).stdout -nics = Popen( +nics = run( ['ifconfig', '-l', 'ether'], stdout=PIPE, - close_fds=True, universal_newlines=True ) -nics_left_over = nics.stdout.read().replace(nic, '').strip() +nics_left_over = nics.stdout.replace(nic, '').strip() nic_list = sorted(re.sub(not_nics_regex, '', nics_left_over).strip().split()) # Stop the script if the nic is not valid or not in the default route. @@ -41,19 +39,17 @@ elif not nic_list: exit(0) -nic_ifconfig = Popen( +nic_ifconfig = run( ['ifconfig', nic], stdout=PIPE, - close_fds=True, universal_newlines=True -).stdout.read() +).stdout -dhcp = Popen( +dhcp = run( ['sysrc', '-n', f'ifconfig_{nic}'], stdout=PIPE, - close_fds=True, universal_newlines=True -).stdout.read() +).stdout active_status = ( 'status: active' in nic_ifconfig, @@ -65,24 +61,26 @@ # Restarting routing adds and nic if there is another one that is active # or associated. if not any(active_status): - os.system(f'service netif stop {nic}') + run(['service', 'netif', 'stop', nic]) + # Create a marker file for link-up.py to detect runtime state change vs boot + with open(f'/tmp/link-down-{nic}', 'w') as f: + f.write('down') if dhcp.strip() == 'DHCP': for current_nic in nic_list: - output = Popen( + output = run( ['ifconfig', current_nic], stdout=PIPE, - close_fds=True, universal_newlines=True ) - nic_ifconfig = output.stdout.read() + nic_ifconfig = output.stdout status_types = [ 'active', 'associated', ] found_status = re.search(f"status: ({'|'.join(status_types)})", nic_ifconfig) - found_inet = re.search("inet(\s|6)", nic_ifconfig) + found_inet = re.search(r"inet(\s|6)", nic_ifconfig) if found_status and found_inet: - os.system(f'service dhclient restart {current_nic}') + run(['service', 'dhclient', 'restart', current_nic]) break else: - os.system('service routing restart') + run(['service', 'routing', 'restart']) diff --git a/src/link-up.py b/src/link-up.py index e58d982..d1021f8 100755 --- a/src/link-up.py +++ b/src/link-up.py @@ -3,56 +3,34 @@ import os import re import sys -from subprocess import Popen, PIPE, run +from subprocess import run, PIPE args = sys.argv if len(args) != 2: exit(1) nic = args[1] -not_nics_regex = "(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ - "ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" +not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ + r"ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" # Stop the script if the nic is not valid. if re.search(not_nics_regex, nic): exit(0) -dhcp = Popen( - ['sysrc', '-n', f'ifconfig_{nic}'], - stdout=PIPE, - close_fds=True, - universal_newlines=True -).stdout.read() - -if os.path.exists(f'/tmp/network-{nic}'): - network = open(f'/tmp/network-{nic}', 'r').read() - if 'attached' in network: - if dhcp.strip() == 'DHCP': - Popen(f'service dhclient quietstart {nic}', shell=True) - else: - Popen(f'service routing restart', shell=True) - with open(f'/tmp/network-{nic}', 'w') as network: - network.writelines(f'linked') - exit(0) - -nic_ifconfig = Popen( - ['ifconfig', nic], - stdout=PIPE, - close_fds=True, - universal_newlines=True -).stdout.read() - -if 'inet ' in nic_ifconfig: - Popen( - f'service routing restart ; ' - f'service dhclient restart {nic}', - shell=True - ) +# This marker file is created by auto-switch.py when the nic is down. +if os.path.exists(f'/tmp/link-down-{nic}'): + nic_ifconfig = run( + ['ifconfig', nic], + stdout=PIPE, + universal_newlines=True + ).stdout + + if 'inet ' not in nic_ifconfig: + run(['service', 'netif', 'start', nic]) + + run(['service', 'routing', 'restart']) + run(['service', 'dhclient', 'restart', nic]) + # Clean up marker file + os.remove(f'/tmp/link-down-{nic}') else: - Popen( - f'service netif start {nic} ; ' - 'sleep 1 ; ' - f'service routing restart ; ' - f'service dhclient restart {nic}', - shell=True - ) + run(['service', 'dhclient', 'quietstart', nic]) diff --git a/src/networkmgr.conf b/src/networkmgr.conf index d14bcee..381e0f1 100644 --- a/src/networkmgr.conf +++ b/src/networkmgr.conf @@ -1,26 +1,26 @@ -notify 100 { +notify 5 { match "system" "IFNET"; match "subsystem" "!(usbus|wlan)[0-9]+"; match "type" "ATTACH"; action "/usr/local/share/networkmgr/setup-nic.py $subsystem"; }; -notify 100 { +notify 5 { match "system" "IFNET"; match "type" "LINK_UP"; media-type "ethernet"; action "/usr/local/share/networkmgr/link-up.py $subsystem"; }; -notify 100 { +notify 5 { match "system" "IFNET"; match "subsystem" "!(usbus|wlan)[0-9]+"; match "type" "LINK_DOWN"; action "/usr/local/share/networkmgr/auto-switch.py $subsystem"; }; -attach 100 { +attach 5 { device-name "$wifi-driver-regex"; action "/usr/local/share/networkmgr/setup-nic.py $device-name"; }; diff --git a/src/setup-nic.py b/src/setup-nic.py index afe04f8..792637d 100755 --- a/src/setup-nic.py +++ b/src/setup-nic.py @@ -5,7 +5,7 @@ import shutil import sys from pathlib import Path -from subprocess import Popen, PIPE +from subprocess import run def file_content(paths): @@ -33,8 +33,8 @@ def file_content(paths): rc_conf_content = file_content(rc_conf_paths) -not_nics_regex = "(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ - "ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" +not_nics_regex = r"(enc|lo|fwe|fwip|tap|plip|pfsync|pflog|ipfw|tun|sl|faith|" \ + r"ppp|bridge|wg|wlan)[0-9]+|vm-[a-z]+" # wifi_driver_regex is taken from devd.conf wifi-driver-regex wifi_driver_regex = "(ath|ath[0-9]+k|bwi|bwn|ipw|iwlwifi|iwi|iwm|iwn|malo|mwl|mt79|otus|" \ @@ -48,16 +48,14 @@ def file_content(paths): wpa_supplicant.touch() shutil.chown(wpa_supplicant, user="root", group="wheel") wpa_supplicant.chmod(0o600) # Secure: root-only, contains passwords - for wlanNum in range(0, 9): - if f'wlan{wlanNum}' not in rc_conf_content: - if f'wlans_{nic}=' not in rc_conf_content: - with rc_conf.open('a') as rc: - rc.writelines(f'wlans_{nic}="wlan{wlanNum}"\n') - rc.writelines(f'ifconfig_wlan{wlanNum}="WPA DHCP"\n') - break + if f'wlans_{nic}=' not in rc_conf_content: + for wlanNum in range(9): + if f'wlan{wlanNum}' not in rc_conf_content: + run(['sysrc', f'wlans_{nic}="wlan{wlanNum}"']) + run(['sysrc', f'ifconfig_wlan{wlanNum}="WPA DHCP"']) + break + run(['/etc/pccard_ether', nic, 'startchildren']) else: if f'ifconfig_{nic}=' not in rc_conf_content: - with rc_conf.open('a') as rc: - rc.writelines(f'ifconfig_{nic}="DHCP"\n') - -Popen(f'/etc/pccard_ether {nic} startchildren', shell=True) + run(['sysrc', f'ifconfig_{nic}=DHCP']) + run(['/etc/pccard_ether', nic, 'start'])