diff options
-rw-r--r-- | data/templates/pppoe/ip-down.script.tmpl | 18 | ||||
-rw-r--r-- | data/templates/pppoe/ip-up.script.tmpl | 36 | ||||
-rw-r--r-- | data/templates/wifi/hostapd.conf.tmpl | 716 | ||||
-rw-r--r-- | data/templates/wifi/wpa_supplicant.conf.tmpl | 9 | ||||
-rw-r--r-- | data/templates/wwan/ip-up.script.tmpl | 11 | ||||
-rw-r--r-- | interface-definitions/interfaces-wireless.xml.in | 2 | ||||
-rw-r--r-- | python/vyos/ifconfig/control.py | 30 | ||||
-rw-r--r-- | python/vyos/ifconfig/ethernet.py | 27 | ||||
-rw-r--r-- | python/vyos/ifconfig/interface.py | 25 | ||||
-rw-r--r-- | python/vyos/util.py | 42 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-openvpn.py | 9 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-pppoe.py | 10 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-vxlan.py | 3 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-wireless.py | 785 | ||||
-rwxr-xr-x | src/conf_mode/interfaces-wirelessmodem.py | 8 | ||||
-rwxr-xr-x | src/conf_mode/vrf.py | 12 | ||||
-rwxr-xr-x | src/op_mode/show_openvpn.py | 4 | ||||
-rwxr-xr-x | src/op_mode/wireguard.py | 2 |
18 files changed, 908 insertions, 841 deletions
diff --git a/data/templates/pppoe/ip-down.script.tmpl b/data/templates/pppoe/ip-down.script.tmpl index f90da02bc..e76875f12 100644 --- a/data/templates/pppoe/ip-down.script.tmpl +++ b/data/templates/pppoe/ip-down.script.tmpl @@ -2,7 +2,6 @@ # As PPPoE is an "on demand" interface we need to re-configure it when it # becomes up - if [ "$6" != "{{ intf }}" ]; then exit fi @@ -11,6 +10,17 @@ fi DIALER_PID=$(cat /var/run/{{ intf }}.pid) logger -t pppd[$DIALER_PID] "executing $0" -# Debian PPP version has no support for replacing an existing default route -# thus we emulate this ba an ip-up script https://phabricator.vyos.net/T2220. -vtysh -c "conf t" -c "no ip route 0.0.0.0/0 {{ intf }}" +# Determine if we are enslaved to a VRF, this is needed to properly insert +# the default route +VRF_NAME="" +if [ -d /sys/class/net/{{ intf }}/upper_* ]; then + # Determine upper (VRF) interface + VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + # Remove upper_ prefix from result string + VRF=${VRF#"upper_"} + # Populate variable to run in VR context + VRF_NAME="vrf ${VRF_NAME}" +fi + +# Always delete default route when interface goes down +vtysh -c "conf t" ${VRF_NAME} -c "no ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME}" diff --git a/data/templates/pppoe/ip-up.script.tmpl b/data/templates/pppoe/ip-up.script.tmpl index c6aa02e9e..4cc779914 100644 --- a/data/templates/pppoe/ip-up.script.tmpl +++ b/data/templates/pppoe/ip-up.script.tmpl @@ -6,28 +6,42 @@ if [ "$6" != "{{ intf }}" ]; then exit fi +set -x + # add some info to syslog DIALER_PID=$(cat /var/run/{{ intf }}.pid) logger -t pppd[$DIALER_PID] "executing $0" +SED_OPT="ip route" +VRF_NAME="" +if [ -d /sys/class/net/{{ intf }}/upper_* ]; then + # Determine upper (VRF) interface + VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) + # Remove upper_ prefix from result string + VRF=${VRF#"upper_"} + # generate new SED command + SED_OPT="vrf ${VRF}" + # generate vtysh option + VRF_NAME="vrf ${VRF}" +fi + # Debian PPP version has no support for replacing an existing default route # thus we emulate this ba an ip-up script https://phabricator.vyos.net/T2220. - {% if 'auto' in default_route -%} - # only insert a new default route if there is no default route configured -routes=$(vtysh -c "show running-config" | sed -n "/ip route/,/!/p" | grep 0.0.0.0/0 | wc -l) -if [ "$routes" -eq 0 ]; then - # No VRF, use default routing table - vtysh -c "conf t" -c "ip route 0.0.0.0/0 {{ intf }}" +routes=$(vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep 0.0.0.0/0 | wc -l) +if [ "$routes" -ne 0 ]; then + exit 1 fi {% elif 'force' in default_route -%} - # Retrieve current static default routes and remove it from the routing table -vtysh -c "show running-config" | sed -n "/ip route/,/!/p" | grep 0.0.0.0/0 | while read route ; do - vtysh -c "conf t" -c "no ${route}" +vtysh -c "show running-config" | sed -n "/${SED_OPT}/,/!/p" | grep 0.0.0.0/0 | while read route ; do + vtysh -c "conf t" ${VTY_OPT} -c "no ${route} ${VRF_NAME}" done -# No VRF, use default routing table -vtysh -c "conf t" -c "ip route 0.0.0.0/0 {{ intf }}" {% endif %} + +# Add default route to default or VRF routing table +vtysh -c "conf t" ${VTY_OPT} -c "ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME}" +logger -t pppd[$DIALER_PID] "added default route via {{ intf }} ${VRF_NAME}" + diff --git a/data/templates/wifi/hostapd.conf.tmpl b/data/templates/wifi/hostapd.conf.tmpl new file mode 100644 index 000000000..8505119e7 --- /dev/null +++ b/data/templates/wifi/hostapd.conf.tmpl @@ -0,0 +1,716 @@ +### Autogenerated by interfaces-wireless.py ###
+{% if description %}
+# Description: {{ description }}
+# User-friendly description of device; up to 32 octets encoded in UTF-8
+device_name={{ description | truncate(32, True) }}
+{% endif %}
+
+# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for
+# management frames with the Host AP driver); wlan0 with many nl80211 drivers
+# Note: This attribute can be overridden by the values supplied with the '-i'
+# command line parameter.
+interface={{ intf }}
+
+# Driver interface type (hostap/wired/none/nl80211/bsd);
+# default: hostap). nl80211 is used with all Linux mac80211 drivers.
+# Use driver=none if building hostapd as a standalone RADIUS server that does
+# not control any wireless/wired driver.
+driver=nl80211
+
+# Levels (minimum value for logged events):
+# 0 = verbose debugging
+# 1 = debugging
+# 2 = informational messages
+# 3 = notification
+# 4 = warning
+logger_syslog=-1
+logger_syslog_level=0
+logger_stdout=-1
+logger_stdout_level=0
+
+{%- if country_code %}
+
+# Country code (ISO/IEC 3166-1). Used to set regulatory domain.
+# Set as needed to indicate country in which device is operating.
+# This can limit available channels and transmit power.
+country_code={{ country_code }}
+
+# Enable IEEE 802.11d. This advertises the country_code and the set of allowed
+# channels and transmit power levels based on the regulatory limits. The
+# country_code setting must be configured with the correct country for
+# IEEE 802.11d functions.
+ieee80211d=1
+{% endif %}
+
+{%- if ssid %}
+
+# SSID to be used in IEEE 802.11 management frames
+ssid={{ ssid }}
+{% endif %}
+
+{%- if channel %}
+
+# Channel number (IEEE 802.11)
+# (default: 0, i.e., not set)
+# Please note that some drivers do not use this value from hostapd and the
+# channel will need to be configured separately with iwconfig.
+#
+# If CONFIG_ACS build option is enabled, the channel can be selected
+# automatically at run time by setting channel=acs_survey or channel=0, both of
+# which will enable the ACS survey based algorithm.
+channel={{ channel }}
+{% endif %}
+
+{%- if mode %}
+
+# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz),
+# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used
+# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this
+# needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs
+# to be set to hw_mode=a. When using ACS (see channel parameter), a
+# special value "any" can be used to indicate that any support band can be used.
+# This special case is currently supported only with drivers with which
+# offloaded ACS is used.
+{% if 'n' in mode -%}
+hw_mode=g
+ieee80211n=1
+{% elif 'ac' in mode -%}
+hw_mode=a
+ieee80211h=1
+ieee80211ac=1
+{% else -%}
+hw_mode={{ mode }}
+{% endif %}
+{% endif %}
+
+# ieee80211w: Whether management frame protection (MFP) is enabled
+# 0 = disabled (default)
+# 1 = optional
+# 2 = required
+{% if 'disabled' in mgmt_frame_protection -%}
+ieee80211w=0
+{% elif 'optional' in mgmt_frame_protection -%}
+ieee80211w=1
+{% elif 'required' in mgmt_frame_protection -%}
+ieee80211w=2
+{% endif %}
+
+# ht_capab: HT capabilities (list of flags)
+# LDPC coding capability: [LDPC] = supported
+# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary
+# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz
+# with secondary channel above the primary channel
+# (20 MHz only if neither is set)
+# Note: There are limits on which channels can be used with HT40- and
+# HT40+. Following table shows the channels that may be available for
+# HT40- and HT40+ use per IEEE 802.11n Annex J:
+# freq HT40- HT40+
+# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan)
+# 5 GHz 40,48,56,64 36,44,52,60
+# (depending on the location, not all of these channels may be available
+# for use)
+# Please note that 40 MHz channels may switch their primary and secondary
+# channels if needed or creation of 40 MHz channel maybe rejected based
+# on overlapping BSSes. These changes are done automatically when hostapd
+# is setting up the 40 MHz channel.
+# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC]
+# (SMPS disabled if neither is set)
+# HT-greenfield: [GF] (disabled if not set)
+# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set)
+# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set)
+# Tx STBC: [TX-STBC] (disabled if not set)
+# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial
+# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC
+# disabled if none of these set
+# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set)
+# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not
+# set)
+# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set)
+# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set)
+# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set)
+{% if cap_ht %}
+ht_capab=
+{%- endif -%}
+
+{%- if cap_ht_40mhz_incapable -%}
+[40-INTOLERANT]
+{%- endif -%}
+
+{%- if cap_ht_delayed_block_ack -%}
+[DELAYED-BA]
+{%- endif -%}
+
+{%- if cap_ht_dsss_cck_40 -%}
+[DSSS_CCK-40]
+{%- endif -%}
+
+{%- if cap_ht_greenfield -%}
+[GF]
+{%- endif -%}
+
+{%- if cap_ht_ldpc -%}
+[LDPC]
+{%- endif -%}
+
+{%- if cap_ht_lsig_protection -%}
+[LSIG-TXOP-PROT]
+{%- endif -%}
+
+{%- if cap_ht_max_amsdu -%}
+[MAX-AMSDU-{{ cap_ht_max_amsdu }}]
+{%- endif -%}
+
+{%- if cap_ht_smps -%}
+[SMPS-{{ cap_ht_smps | upper }}]
+{%- endif -%}
+
+{%- if cap_ht_chan_set_width -%}
+{%- for csw in cap_ht_chan_set_width -%}
+[{{ csw | upper }}]
+{%- endfor -%}
+{%- endif -%}
+
+{%- if cap_ht_short_gi -%}
+{%- for gi in cap_ht_short_gi -%}
+[SHORT-GI-{{ gi }}]
+{%- endfor -%}
+{%- endif -%}
+
+{%- if cap_ht_stbc_tx -%}
+[TX-STBC]
+{%- endif -%}
+{%- if cap_ht_stbc_rx -%}
+[RX-STBC{{ cap_ht_stbc_rx }}]
+{%- endif %}
+
+# Required for full HT and VHT functionality
+wme_enabled=1
+
+{% if cap_ht_powersave -%}
+# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD]
+# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver)
+uapsd_advertisement_enabled=1
+{%- endif %}
+
+{% if cap_req_ht -%}
+# Require stations to support HT PHY (reject association if they do not)
+require_ht=1
+{% endif %}
+
+{%- if cap_vht_chan_set_width -%}
+vht_oper_chwidth={{ cap_vht_chan_set_width }}
+{%- endif -%}
+
+# vht_capab: VHT capabilities (list of flags)
+#
+# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454]
+# Indicates maximum MPDU length
+# 0 = 3895 octets (default)
+# 1 = 7991 octets
+# 2 = 11454 octets
+# 3 = reserved
+#
+# supported_chan_width: [VHT160] [VHT160-80PLUS80]
+# Indicates supported Channel widths
+# 0 = 160 MHz & 80+80 channel widths are not supported (default)
+# 1 = 160 MHz channel width is supported
+# 2 = 160 MHz & 80+80 channel widths are supported
+# 3 = reserved
+#
+# Rx LDPC coding capability: [RXLDPC]
+# Indicates support for receiving LDPC coded pkts
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Short GI for 80 MHz: [SHORT-GI-80]
+# Indicates short GI support for reception of packets transmitted with TXVECTOR
+# params format equal to VHT and CBW = 80Mhz
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Short GI for 160 MHz: [SHORT-GI-160]
+# Indicates short GI support for reception of packets transmitted with TXVECTOR
+# params format equal to VHT and CBW = 160Mhz
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Tx STBC: [TX-STBC-2BY1]
+# Indicates support for the transmission of at least 2x1 STBC
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234]
+# Indicates support for the reception of PPDUs using STBC
+# 0 = Not supported (default)
+# 1 = support of one spatial stream
+# 2 = support of one and two spatial streams
+# 3 = support of one, two and three spatial streams
+# 4 = support of one, two, three and four spatial streams
+# 5,6,7 = reserved
+#
+# SU Beamformer Capable: [SU-BEAMFORMER]
+# Indicates support for operation as a single user beamformer
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# SU Beamformee Capable: [SU-BEAMFORMEE]
+# Indicates support for operation as a single user beamformee
+# 0 = Not supported (default)
+# 1 = Supported
+#
+# Compressed Steering Number of Beamformer Antennas Supported:
+# [BF-ANTENNA-2] [BF-ANTENNA-3] [BF-ANTENNA-4]
+# Beamformee's capability indicating the maximum number of beamformer
+# antennas the beamformee can support when sending compressed beamforming
+# feedback
+# If SU beamformer capable, set to maximum value minus 1
+# else reserved (default)
+#
+# Number of Sounding Dimensions:
+# [SOUNDING-DIMENSION-2] [SOUNDING-DIMENSION-3] [SOUNDING-DIMENSION-4]
+# Beamformer's capability indicating the maximum value of the NUM_STS parameter
+# in the TXVECTOR of a VHT NDP
+# If SU beamformer capable, set to maximum value minus 1
+# else reserved (default)
+#
+# MU Beamformer Capable: [MU-BEAMFORMER]
+# Indicates support for operation as an MU beamformer
+# 0 = Not supported or sent by Non-AP STA (default)
+# 1 = Supported
+#
+# VHT TXOP PS: [VHT-TXOP-PS]
+# Indicates whether or not the AP supports VHT TXOP Power Save Mode
+# or whether or not the STA is in VHT TXOP Power Save mode
+# 0 = VHT AP doesn't support VHT TXOP PS mode (OR) VHT STA not in VHT TXOP PS
+# mode
+# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT STA is in VHT TXOP power save
+# mode
+#
+# +HTC-VHT Capable: [HTC-VHT]
+# Indicates whether or not the STA supports receiving a VHT variant HT Control
+# field.
+# 0 = Not supported (default)
+# 1 = supported
+#
+# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7]
+# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv
+# This field is an integer in the range of 0 to 7.
+# The length defined by this field is equal to
+# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets
+#
+# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3]
+# Indicates whether or not the STA supports link adaptation using VHT variant
+# HT Control field
+# If +HTC-VHTcapable is 1
+# 0 = (no feedback) if the STA does not provide VHT MFB (default)
+# 1 = reserved
+# 2 = (Unsolicited) if the STA provides only unsolicited VHT MFB
+# 3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the
+# STA provides unsolicited VHT MFB
+# Reserved if +HTC-VHTcapable is 0
+#
+# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN]
+# Indicates the possibility of Rx antenna pattern change
+# 0 = Rx antenna pattern might change during the lifetime of an association
+# 1 = Rx antenna pattern does not change during the lifetime of an association
+#
+# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN]
+# Indicates the possibility of Tx antenna pattern change
+# 0 = Tx antenna pattern might change during the lifetime of an association
+# 1 = Tx antenna pattern does not change during the lifetime of an association
+{% if cap_vht %}
+vht_capab=
+{%- endif -%}
+
+{%- if cap_vht_max_mpdu -%}
+[MAX-MPDU-{{ cap_vht_max_mpdu }}]
+{%- endif -%}
+
+{%- if cap_vht_max_mpdu_exp -%}
+[MAX-A-MPDU-LEN-EXP{{ cap_vht_max_mpdu_exp }}]
+{%- endif -%}
+
+{%- if cap_vht_chan_set_width -%}
+{%- if '2' in cap_vht_chan_set_width -%}
+[VHT160]
+{%- elif '3' in cap_vht_chan_set_width -%}
+[VHT160-80PLUS80]
+{%- endif -%}
+{%- endif -%}
+
+{%- if cap_vht_stbc_tx -%}
+[TX-STBC-2BY1]
+{%- endif -%}
+
+{%- if cap_vht_stbc_rx -%}
+[RX-STBC-{{ cap_vht_stbc_rx }}]
+{%- endif -%}
+
+{%- if cap_vht_link_adaptation -%}
+{%- if 'unsolicited' in cap_vht_link_adaptation -%}
+[VHT-LINK-ADAPT2]
+{%- elif 'both' in cap_vht_link_adaptation -%}
+[VHT-LINK-ADAPT3]
+{%- endif -%}
+{%- endif -%}
+
+{%- if cap_vht_short_gi -%}
+{%- for gi in cap_vht_short_gi -%}
+[SHORT-GI-{{ gi }}]
+{%- endfor -%}
+{%- endif -%}
+
+{%- if cap_vht_ldpc -%}
+[RXLDPC]
+{%- endif -%}
+
+{%- if cap_vht_tx_powersave -%}
+[VHT-TXOP-PS]
+{%- endif -%}
+
+{%- if cap_vht_vht_cf -%}
+[HTC-VHT]
+{%- endif -%}
+
+{%- if cap_vht_beamform -%}
+{%- for beamform in cap_vht_beamform -%}
+{%- if 'single-user-beamformer' in beamform -%}
+[SU-BEAMFORMER]
+{%- elif 'single-user-beamformee' in beamform -%}
+[SU-BEAMFORMEE]
+{%- elif 'multi-user-beamformer' in beamform -%}
+[MU-BEAMFORMER]
+{%- elif 'multi-user-beamformee' in beamform -%}
+[MU-BEAMFORMEE]
+{%- endif -%}
+{%- endfor -%}
+{%- endif -%}
+
+{%- if cap_vht_antenna_fixed -%}
+[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN]
+{%- endif -%}
+
+{%- if cap_vht_antenna_cnt -%}
+{%- for beamform in cap_vht_beamform -%}
+{%- if 'single-user-beamformer' in beamform -%}
+[BF-ANTENNA-{{ cap_vht_antenna_cnt|int -1 }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt|int -1}}]
+{%- else -%}
+[BF-ANTENNA-{{ cap_vht_antenna_cnt }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt }}]
+{%- endif -%}
+{%- endfor -%}
+{%- endif %}
+
+# ieee80211n: Whether IEEE 802.11n (HT) is enabled
+# 0 = disabled (default)
+# 1 = enabled
+# Note: You will also need to enable WMM for full HT functionality.
+# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band.
+{% if cap_req_vht -%}
+ieee80211n=0
+# Require stations to support VHT PHY (reject association if they do not)
+require_vht=1
+{% endif %}
+
+{% if cap_vht_center_freq_1 -%}
+# center freq = 5 GHz + (5 * index)
+# So index 42 gives center freq 5.210 GHz
+# which is channel 42 in 5G band
+vht_oper_centr_freq_seg0_idx={{ cap_vht_center_freq_1 }}
+{% endif %}
+
+{% if cap_vht_center_freq_2 -%}
+# center freq = 5 GHz + (5 * index)
+# So index 159 gives center freq 5.795 GHz
+# which is channel 159 in 5G band
+vht_oper_centr_freq_seg1_idx={{ cap_vht_center_freq_2 }}
+{% endif %}
+
+{% if disable_broadcast_ssid -%}
+# Send empty SSID in beacons and ignore probe request frames that do not
+# specify full SSID, i.e., require stations to know SSID.
+# default: disabled (0)
+# 1 = send empty (length=0) SSID in beacon and ignore probe request for
+# broadcast SSID
+# 2 = clear SSID (ASCII 0), but keep the original length (this may be required
+# with some clients that do not support empty SSID) and ignore probe
+# requests for broadcast SSID
+ignore_broadcast_ssid=1
+{% endif %}
+
+# Station MAC address -based authentication
+# Please note that this kind of access control requires a driver that uses
+# hostapd to take care of management frame processing and as such, this can be
+# used with driver=hostap or driver=nl80211, but not with driver=atheros.
+# 0 = accept unless in deny list
+# 1 = deny unless in accept list
+# 2 = use external RADIUS server (accept/deny lists are searched first)
+macaddr_acl=0
+
+{% if max_stations -%}
+# Maximum number of stations allowed in station table. New stations will be
+# rejected after the station table is full. IEEE 802.11 has a limit of 2007
+# different association IDs, so this number should not be larger than that.
+# (default: 2007)
+max_num_sta={{ max_stations }}
+{% endif %}
+
+{% if isolate_stations -%}
+# Client isolation can be used to prevent low-level bridging of frames between
+# associated stations in the BSS. By default, this bridging is allowed.
+ap_isolate=1
+{% endif %}
+
+{% if reduce_transmit_power -%}
+# Add Power Constraint element to Beacon and Probe Response frames
+# This config option adds Power Constraint element when applicable and Country
+# element is added. Power Constraint element is required by Transmit Power
+# Control. This can be used only with ieee80211d=1.
+# Valid values are 0..255.
+local_pwr_constraint={{ reduce_transmit_power }}
+{% endif %}
+
+{% if expunge_failing_stations -%}
+# Disassociate stations based on excessive transmission failures or other
+# indications of connection loss. This depends on the driver capabilities and
+# may not be available with all drivers.
+disassoc_low_ack=1
+{% endif %}
+
+{% if sec_wep -%}
+# IEEE 802.11 specifies two authentication algorithms. hostapd can be
+# configured to allow both of these or only one. Open system authentication
+# should be used with IEEE 802.1X.
+# Bit fields of allowed authentication algorithms:
+# bit 0 = Open System Authentication
+# bit 1 = Shared Key Authentication (requires WEP)
+auth_algs=2
+
+# WEP rekeying (disabled if key lengths are not set or are set to 0)
+# Key lengths for default/broadcast and individual/unicast keys:
+# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits)
+# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits)
+wep_key_len_broadcast=5
+wep_key_len_unicast=5
+
+# Static WEP key configuration
+#
+# The key number to use when transmitting.
+# It must be between 0 and 3, and the corresponding key must be set.
+# default: not set
+wep_default_key=0
+
+# The WEP keys to use.
+# A key may be a quoted string or unquoted hexadecimal digits.
+# The key length should be 5, 13, or 16 characters, or 10, 26, or 32
+# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or
+# 128-bit (152-bit) WEP is used.
+# Only the default key must be supplied; the others are optional.
+{% if sec_wep_key -%}
+{% for key in sec_wep_key -%}
+wep_key{{ loop.index -1 }}={{ key}}
+{% endfor %}
+{%- endif %}
+
+{% elif sec_wpa -%}
+##### WPA/IEEE 802.11i configuration ##########################################
+
+# Enable WPA. Setting this variable configures the AP to require WPA (either
+# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either
+# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK.
+# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice.
+# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys),
+# RADIUS authentication server must be configured, and WPA-EAP must be included
+# in wpa_key_mgmt.
+# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0)
+# and/or WPA2 (full IEEE 802.11i/RSN):
+# bit0 = WPA
+# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled)
+{% if 'both' in sec_wpa_mode -%}
+wpa=3
+{%- elif 'wpa2' in sec_wpa_mode -%}
+wpa=2
+{%- elif 'wpa' in sec_wpa_mode -%}
+wpa=1
+{%- endif %}
+
+{% if sec_wpa_cipher -%}
+# Set of accepted cipher suites (encryption algorithms) for pairwise keys
+# (unicast packets). This is a space separated list of algorithms:
+# CCMP = AES in Counter mode with CBC-MAC (CCMP-128)
+# TKIP = Temporal Key Integrity Protocol
+# CCMP-256 = AES in Counter mode with CBC-MAC with 256-bit key
+# GCMP = Galois/counter mode protocol (GCMP-128)
+# GCMP-256 = Galois/counter mode protocol with 256-bit key
+# Group cipher suite (encryption algorithm for broadcast and multicast frames)
+# is automatically selected based on this configuration. If only CCMP is
+# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise,
+# TKIP will be used as the group cipher. The optional group_cipher parameter can
+# be used to override this automatic selection.
+{% if 'wpa2' in sec_wpa_mode -%}
+# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value)
+rsn_pairwise={{ sec_wpa_cipher | join(" ") }}
+{% else -%}
+# Pairwise cipher for WPA (v1) (default: TKIP)
+wpa_pairwise={{ sec_wpa_cipher | join(" ") }}
+{%- endif -%}
+{% endif %}
+
+{% if sec_wpa_passphrase -%}
+# IEEE 802.11 specifies two authentication algorithms. hostapd can be
+# configured to allow both of these or only one. Open system authentication
+# should be used with IEEE 802.1X.
+# Bit fields of allowed authentication algorithms:
+# bit 0 = Open System Authentication
+# bit 1 = Shared Key Authentication (requires WEP)
+auth_algs=1
+
+# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit
+# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase
+# (8..63 characters) that will be converted to PSK. This conversion uses SSID
+# so the PSK changes when ASCII passphrase is used and the SSID is changed.
+wpa_passphrase={{ sec_wpa_passphrase }}
+
+# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
+# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
+# added to enable SHA256-based stronger algorithms.
+# WPA-PSK = WPA-Personal / WPA2-Personal
+# WPA-PSK-SHA256 = WPA2-Personal using SHA256
+wpa_key_mgmt=WPA-PSK
+
+{% elif sec_wpa_radius -%}
+##### IEEE 802.1X-2004 related configuration ##################################
+# Require IEEE 802.1X authorization
+ieee8021x=1
+
+# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The
+# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be
+# added to enable SHA256-based stronger algorithms.
+# WPA-EAP = WPA-Enterprise / WPA2-Enterprise
+# WPA-EAP-SHA256 = WPA2-Enterprise using SHA256
+wpa_key_mgmt=WPA-EAP
+
+{% if sec_wpa_radius_source -%}
+# RADIUS client forced local IP address for the access point
+# Normally the local IP address is determined automatically based on configured
+# IP addresses, but this field can be used to force a specific address to be
+# used, e.g., when the device has multiple IP addresses.
+radius_client_addr={{ sec_wpa_radius_source }}
+
+# The own IP address of the access point (used as NAS-IP-Address)
+own_ip_addr={{ sec_wpa_radius_source }}
+{% else %}
+# The own IP address of the access point (used as NAS-IP-Address)
+own_ip_addr=127.0.0.1
+{% endif %}
+
+{% for radius in sec_wpa_radius -%}
+{%- if not radius.disabled -%}
+# RADIUS authentication server
+auth_server_addr={{ radius.server }}
+auth_server_port={{ radius.port }}
+auth_server_shared_secret={{ radius.key }}
+{% if radius.acc_port -%}
+# RADIUS accounting server
+acct_server_addr={{ radius.server }}
+acct_server_port={{ radius.acc_port }}
+acct_server_shared_secret={{ radius.key }}
+{% endif %}
+{% endif %}
+{% endfor %}
+
+{% endif %}
+
+{% else %}
+# Open system
+auth_algs=1
+{% endif %}
+
+# TX queue parameters (EDCF / bursting)
+# tx_queue_<queue name>_<param>
+# queues: data0, data1, data2, data3
+# (data0 is the highest priority queue)
+# parameters:
+# aifs: AIFS (default 2)
+# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191,
+# 16383, 32767)
+# cwmax: cwMax (same values as cwMin, cwMax >= cwMin)
+# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for
+# bursting
+#
+# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):
+# These parameters are used by the access point when transmitting frames
+# to the clients.
+#
+# Low priority / AC_BK = background
+tx_queue_data3_aifs=7
+tx_queue_data3_cwmin=15
+tx_queue_data3_cwmax=1023
+tx_queue_data3_burst=0
+# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0
+#
+# Normal priority / AC_BE = best effort
+tx_queue_data2_aifs=3
+tx_queue_data2_cwmin=15
+tx_queue_data2_cwmax=63
+tx_queue_data2_burst=0
+# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0
+#
+# High priority / AC_VI = video
+tx_queue_data1_aifs=1
+tx_queue_data1_cwmin=7
+tx_queue_data1_cwmax=15
+tx_queue_data1_burst=3.0
+# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0
+#
+# Highest priority / AC_VO = voice
+tx_queue_data0_aifs=1
+tx_queue_data0_cwmin=3
+tx_queue_data0_cwmax=7
+tx_queue_data0_burst=1.5
+
+# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e):
+# for 802.11a or 802.11g networks
+# These parameters are sent to WMM clients when they associate.
+# The parameters will be used by WMM clients for frames transmitted to the
+# access point.
+#
+# note - txop_limit is in units of 32microseconds
+# note - acm is admission control mandatory flag. 0 = admission control not
+# required, 1 = mandatory
+# note - Here cwMin and cmMax are in exponent form. The actual cw value used
+# will be (2^n)-1 where n is the value given here. The allowed range for these
+# wmm_ac_??_{cwmin,cwmax} is 0..15 with cwmax >= cwmin.
+#
+wmm_enabled=1
+
+# Low priority / AC_BK = background
+wmm_ac_bk_cwmin=4
+wmm_ac_bk_cwmax=10
+wmm_ac_bk_aifs=7
+wmm_ac_bk_txop_limit=0
+wmm_ac_bk_acm=0
+# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10
+#
+# Normal priority / AC_BE = best effort
+wmm_ac_be_aifs=3
+wmm_ac_be_cwmin=4
+wmm_ac_be_cwmax=10
+wmm_ac_be_txop_limit=0
+wmm_ac_be_acm=0
+# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7
+#
+# High priority / AC_VI = video
+wmm_ac_vi_aifs=2
+wmm_ac_vi_cwmin=3
+wmm_ac_vi_cwmax=4
+wmm_ac_vi_txop_limit=94
+wmm_ac_vi_acm=0
+# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188
+#
+# Highest priority / AC_VO = voice
+wmm_ac_vo_aifs=2
+wmm_ac_vo_cwmin=2
+wmm_ac_vo_cwmax=3
+wmm_ac_vo_txop_limit=47
+wmm_ac_vo_acm=0
+
diff --git a/data/templates/wifi/wpa_supplicant.conf.tmpl b/data/templates/wifi/wpa_supplicant.conf.tmpl new file mode 100644 index 000000000..4a14cd309 --- /dev/null +++ b/data/templates/wifi/wpa_supplicant.conf.tmpl @@ -0,0 +1,9 @@ +# WPA supplicant config
+network={
+ ssid="{{ ssid }}"
+{%- if sec_wpa_passphrase %}
+ psk="{{ sec_wpa_passphrase }}"
+{% else %}
+ key_mgmt=NONE
+{% endif %}
+}
diff --git a/data/templates/wwan/ip-up.script.tmpl b/data/templates/wwan/ip-up.script.tmpl index 7382309ac..89e42a23a 100644 --- a/data/templates/wwan/ip-up.script.tmpl +++ b/data/templates/wwan/ip-up.script.tmpl @@ -7,6 +7,8 @@ if [ -z "$(echo $tty | egrep "tty(USB|ACM)")" ]; then exit 0 fi +DIALER_PID=$(cat /var/run/{{ intf }}.pid) + # Determine if we are enslaved to a VRF, this is needed to properly insert # the default route VRF_NAME="" @@ -15,12 +17,9 @@ if [ -d /sys/class/net/{{ intf }}/upper_* ]; then VRF=$(basename $(ls -d /sys/class/net/{{ intf }}/upper_*)) # Remove upper_ prefix from result string VRF=${VRF#"upper_"} - # Populate variable to run in VR context - VRF_NAME=" -c vrf ${VRF_NAME} " + VRF_NAME="vrf ${VRF}" fi # Apply default route to either default or VRF routing table -vtysh -c "conf t" ${VRF_NAME} -c "ip route 0.0.0.0/0 {{ intf }} {{ metric }}" - -DIALER_PID=$(cat /var/run/{{ intf }}.pid) -logger -t pppd[$DIALER_PID] "added default route via {{ intf }} metric {{ metric }}" +vtysh -c "conf t" -c "ip route 0.0.0.0/0 {{ intf }} ${VRF_NAME} {{ metric }}" +logger -t pppd[$DIALER_PID] "added default route via {{ intf }} metric {{ metric }} ${VRF_NAME}" diff --git a/interface-definitions/interfaces-wireless.xml.in b/interface-definitions/interfaces-wireless.xml.in index 12736510b..490e63a42 100644 --- a/interface-definitions/interfaces-wireless.xml.in +++ b/interface-definitions/interfaces-wireless.xml.in @@ -320,7 +320,7 @@ <properties> <help>VHT link adaptation capabilities</help> <completionHelp> - <list>single-user-beamformer single-user-beamformee multi-user-beamformer multi-user-beamformee</list> + <list>unsolicited both</list> </completionHelp> <valueHelp> <format>unsolicited</format> diff --git a/python/vyos/ifconfig/control.py b/python/vyos/ifconfig/control.py index c1a073aef..c7a2fa2d6 100644 --- a/python/vyos/ifconfig/control.py +++ b/python/vyos/ifconfig/control.py @@ -15,8 +15,9 @@ import os -from subprocess import Popen, PIPE, STDOUT +from vyos.util import debug, debug_msg +from vyos.util import popen, cmd from vyos.ifconfig.register import Register @@ -32,27 +33,18 @@ class Control(Register): # to prevent this, debugging can be explicitely disabled # if debug is not explicitely disabled the the config, enable it - self.debug = kargs.get('debug', True) + self.debug = '' + if kargs.get('debug', True): + self.debug = debug('ifconfig') - def _debug_msg(self, msg): - if os.path.isfile('/tmp/vyos.ifconfig.debug') and self.debug: - print('DEBUG/{:<6} {}'.format(self.config['ifname'], msg)) + def _debug_msg (self, message): + return debug_msg(message, self.debug) def _popen(self, command): - p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) - tmp = p.communicate()[0].strip() - self._debug_msg(f"cmd '{command}'") - decoded = tmp.decode() - if decoded: - self._debug_msg(f"returned:\n{decoded}") - return decoded, p.returncode + return popen(command, self.debug) def _cmd(self, command): - decoded, code = self._popen(command) - if code != 0: - # error code can be recovered with .errno - raise OSError(code, f'{command}\nreturned: {decoded}') - return decoded + return cmd(command, self.debug) def _get_command(self, config, name): """ @@ -79,6 +71,10 @@ class Control(Register): if convert: value = convert(value) + possible = self._command_set[name].get('possible', None) + if possible and not possible(config['ifname'], value): + return False + config = {**config, **{'value': value}} cmd = self._command_set[name]['shellcmd'].format(**config) diff --git a/python/vyos/ifconfig/ethernet.py b/python/vyos/ifconfig/ethernet.py index 50552dc71..c18d2e72f 100644 --- a/python/vyos/ifconfig/ethernet.py +++ b/python/vyos/ifconfig/ethernet.py @@ -18,7 +18,7 @@ import re from vyos.ifconfig.interface import Interface from vyos.ifconfig.vlan import VLAN - +from vyos.util import popen from vyos.validate import * @@ -43,27 +43,36 @@ class EthernetIf(Interface): } } + @staticmethod + def feature(ifname, option, value): + out, code = popen(f'/sbin/ethtool -K {ifname} {option} {value}','ifconfig') + return False _command_set = {**Interface._command_set, **{ 'gro': { 'validate': lambda v: assert_list(v, ['on', 'off']), - 'shellcmd': '/sbin/ethtool -K {ifname} gro {value}', + 'possible': lambda i, v: EthernetIf.feature(i, 'gro', v), + # 'shellcmd': '/sbin/ethtool -K {ifname} gro {value}', }, 'gso': { 'validate': lambda v: assert_list(v, ['on', 'off']), - 'shellcmd': '/sbin/ethtool -K {ifname} gso {value}', + 'possible': lambda i, v: EthernetIf.feature(i, 'gso', v), + # 'shellcmd': '/sbin/ethtool -K {ifname} gso {value}', }, 'sg': { 'validate': lambda v: assert_list(v, ['on', 'off']), - 'shellcmd': '/sbin/ethtool -K {ifname} sg {value}', + 'possible': lambda i, v: EthernetIf.feature(i, 'sg', v), + # 'shellcmd': '/sbin/ethtool -K {ifname} sg {value}', }, 'tso': { 'validate': lambda v: assert_list(v, ['on', 'off']), - 'shellcmd': '/sbin/ethtool -K {ifname} tso {value}', + 'possible': lambda i, v: EthernetIf.feature(i, 'tso', v), + # 'shellcmd': '/sbin/ethtool -K {ifname} tso {value}', }, 'ufo': { 'validate': lambda v: assert_list(v, ['on', 'off']), - 'shellcmd': '/sbin/ethtool -K {ifname} ufo {value}', + 'possible': lambda i, v: EthernetIf.feature(i, 'ufo', v), + # 'shellcmd': '/sbin/ethtool -K {ifname} ufo {value}', }, }} @@ -245,8 +254,4 @@ class EthernetIf(Interface): >>> i = EthernetIf('eth0') >>> i.set_udp_offload('on') """ - if state not in ['on', 'off']: - raise ValueError('state must be "on" or "off"') - - cmd = '/sbin/ethtool -K {} ufo {}'.format(self.config['ifname'], state) - return self._cmd(cmd) + return self.set_interface('ufo', state) diff --git a/python/vyos/ifconfig/interface.py b/python/vyos/ifconfig/interface.py index 4a34f96d6..96057a943 100644 --- a/python/vyos/ifconfig/interface.py +++ b/python/vyos/ifconfig/interface.py @@ -39,6 +39,8 @@ class Interface(DHCP): required = [] default = { 'type': '', + 'debug': True, + 'create': True, } definition = { 'section': '', @@ -174,15 +176,26 @@ class Interface(DHCP): super().__init__(ifname, **kargs) if not os.path.exists('/sys/class/net/{}'.format(self.config['ifname'])): + # Any instance of Interface, such as Interface('eth0') + # can be used safely to access the generic function in this class + # as 'type' is unset, the class can not be created if not self.config['type']: raise Exception('interface "{}" not found'.format(self.config['ifname'])) - for k in self.required: - if k not in kargs: - name = self.default['type'] - raise ConfigError(f'missing required option {k} for {name} {ifname} creation') - - self._create() + # Should an Instance of a child class (EthernetIf, DummyIf, ..) + # be required, then create should be set to False to not accidentally create it. + # In case a subclass does not define it, we use get to set the default to True + if self.config.get('create',True): + for k in self.required: + if k not in kargs: + name = self.default['type'] + raise ConfigError(f'missing required option {k} for {name} {ifname} creation') + + self._create() + # If we can not connect to the interface then let the caller know + # as the class could not be correctly initialised + else: + raise Exception('interface "{}" not found'.format(self.config['ifname'])) # list of assigned IP addresses self._addr = [] diff --git a/python/vyos/util.py b/python/vyos/util.py index 5807c837d..c8ab43c11 100644 --- a/python/vyos/util.py +++ b/python/vyos/util.py @@ -16,6 +16,44 @@ import os import re import sys +from subprocess import Popen, PIPE, STDOUT + + +# debugging + + +def debug(flag): + return flag if os.path.isfile(f'/tmp/vyos.{flag}.debug') else '' + + +def debug_msg(message, section=''): + if section: + print(f'DEBUG/{section:<6} {message}') + + +# commands + + +def popen(command, section=''): + p = Popen(command, stdout=PIPE, stderr=STDOUT, shell=True) + tmp = p.communicate()[0].strip() + debug_msg(f"cmd '{command}'", section) + decoded = tmp.decode() + if decoded: + debug_msg(f"returned:\n{decoded}", section) + return decoded, p.returncode + + +def cmd(command, section=''): + decoded, code = popen(command, section) + if code != 0: + # error code can be recovered with .errno + raise OSError(code, f'{command}\nreturned: {decoded}') + return decoded + + +# file manipulation + def subprocess_cmd(command): @@ -43,11 +81,11 @@ def chown_file(path, user, group): os.chown(path, uid, gid) -def chmod_x_file(path): +def chmod_x(path): """ make file executable """ from stat import S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IXGRP, S_IROTH, S_IXOTH - if os.path.isfile(path): + if os.path.exists(path): bitmask = S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | \ S_IROTH | S_IXOTH os.chmod(path, bitmask) diff --git a/src/conf_mode/interfaces-openvpn.py b/src/conf_mode/interfaces-openvpn.py index fb2d6e6d9..9bac4d759 100755 --- a/src/conf_mode/interfaces-openvpn.py +++ b/src/conf_mode/interfaces-openvpn.py @@ -66,6 +66,10 @@ proto {% if 'tcp-active' in protocol -%}tcp-client{% elif 'tcp-passive' in proto local {{ local_host }} {% endif %} +{%- if mode == 'server' and protocol == 'udp' and not local_host %} +multihome +{% endif %} + {%- if local_port %} lport {{ local_port }} {% endif %} @@ -308,7 +312,7 @@ default_config_data = { 'ncp_ciphers': '', 'options': [], 'persistent_tunnel': False, - 'protocol': '', + 'protocol': 'udp', 'redirect_gateway': '', 'remote_address': '', 'remote_host': [], @@ -512,8 +516,7 @@ def get_config(): # OpenVPN operation mode if conf.exists('mode'): - mode = conf.return_value('mode') - openvpn['mode'] = mode + openvpn['mode'] = conf.return_value('mode') # Additional OpenVPN options if conf.exists('openvpn-option'): diff --git a/src/conf_mode/interfaces-pppoe.py b/src/conf_mode/interfaces-pppoe.py index 37934263c..a396af4ea 100755 --- a/src/conf_mode/interfaces-pppoe.py +++ b/src/conf_mode/interfaces-pppoe.py @@ -24,7 +24,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.defaults import directories as vyos_data_dir from vyos.ifconfig import Interface -from vyos.util import chown_file, chmod_x_file, subprocess_cmd +from vyos.util import chown_file, chmod_x, subprocess_cmd from vyos import ConfigError default_config_data = { @@ -223,10 +223,10 @@ def generate(pppoe): f.write(config_text) # make generated script file executable - chmod_x_file(script_pppoe_pre_up) - chmod_x_file(script_pppoe_ip_up) - chmod_x_file(script_pppoe_ip_down) - chmod_x_file(script_pppoe_ipv6_up) + chmod_x(script_pppoe_pre_up) + chmod_x(script_pppoe_ip_up) + chmod_x(script_pppoe_ip_down) + chmod_x(script_pppoe_ipv6_up) return None diff --git a/src/conf_mode/interfaces-vxlan.py b/src/conf_mode/interfaces-vxlan.py index 3d2638c6f..1f9636729 100755 --- a/src/conf_mode/interfaces-vxlan.py +++ b/src/conf_mode/interfaces-vxlan.py @@ -160,9 +160,6 @@ def verify(vxlan): 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') - if not vxlan['vni']: raise ConfigError('Must configure VNI for VXLAN') diff --git a/src/conf_mode/interfaces-wireless.py b/src/conf_mode/interfaces-wireless.py index b6e62b0aa..85f784a2a 100755 --- a/src/conf_mode/interfaces-wireless.py +++ b/src/conf_mode/interfaces-wireless.py @@ -15,763 +15,26 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. import os - -from jinja2 import Template -from copy import deepcopy from sys import exit -from stat import S_IRWXU,S_IRGRP,S_IXGRP,S_IROTH,S_IXOTH -from pwd import getpwnam -from grp import getgrnam from re import findall +from copy import deepcopy +from jinja2 import FileSystemLoader, Environment + from subprocess import Popen, PIPE from netifaces import interfaces -from netaddr import * -from vyos import ConfigError -from vyos.configdict import list_diff, vlan_to_dict from vyos.config import Config +from vyos.configdict import list_diff, vlan_to_dict +from vyos.defaults import directories as vyos_data_dir from vyos.ifconfig import WiFiIf from vyos.ifconfig_vlan import apply_vlan_config, verify_vlan_config -from vyos.util import process_running +from vyos.util import process_running, chmod_x +from vyos import ConfigError user = 'root' group = 'vyattacfg' -# Please be careful if you edit the template. -config_hostapd_tmpl = """ -### Autogenerated by interfaces-wireless.py ### -{% if description %} -# Description: {{ description }} -# User-friendly description of device; up to 32 octets encoded in UTF-8 -device_name={{ description | truncate(32, True) }} -{% endif %} - -# AP netdevice name (without 'ap' postfix, i.e., wlan0 uses wlan0ap for -# management frames with the Host AP driver); wlan0 with many nl80211 drivers -# Note: This attribute can be overridden by the values supplied with the '-i' -# command line parameter. -interface={{ intf }} - -# Driver interface type (hostap/wired/none/nl80211/bsd); -# default: hostap). nl80211 is used with all Linux mac80211 drivers. -# Use driver=none if building hostapd as a standalone RADIUS server that does -# not control any wireless/wired driver. -driver=nl80211 - -# Levels (minimum value for logged events): -# 0 = verbose debugging -# 1 = debugging -# 2 = informational messages -# 3 = notification -# 4 = warning -logger_syslog=-1 -logger_syslog_level=0 -logger_stdout=-1 -logger_stdout_level=0 - -{%- if country_code %} - -# Country code (ISO/IEC 3166-1). Used to set regulatory domain. -# Set as needed to indicate country in which device is operating. -# This can limit available channels and transmit power. -country_code={{ country_code }} - -# Enable IEEE 802.11d. This advertises the country_code and the set of allowed -# channels and transmit power levels based on the regulatory limits. The -# country_code setting must be configured with the correct country for -# IEEE 802.11d functions. -ieee80211d=1 -{% endif %} - -{%- if ssid %} - -# SSID to be used in IEEE 802.11 management frames -ssid={{ ssid }} -{% endif %} - -{%- if channel %} - -# Channel number (IEEE 802.11) -# (default: 0, i.e., not set) -# Please note that some drivers do not use this value from hostapd and the -# channel will need to be configured separately with iwconfig. -# -# If CONFIG_ACS build option is enabled, the channel can be selected -# automatically at run time by setting channel=acs_survey or channel=0, both of -# which will enable the ACS survey based algorithm. -channel={{ channel }} -{% endif %} - -{%- if mode %} - -# Operation mode (a = IEEE 802.11a (5 GHz), b = IEEE 802.11b (2.4 GHz), -# g = IEEE 802.11g (2.4 GHz), ad = IEEE 802.11ad (60 GHz); a/g options are used -# with IEEE 802.11n (HT), too, to specify band). For IEEE 802.11ac (VHT), this -# needs to be set to hw_mode=a. For IEEE 802.11ax (HE) on 6 GHz this needs -# to be set to hw_mode=a. When using ACS (see channel parameter), a -# special value "any" can be used to indicate that any support band can be used. -# This special case is currently supported only with drivers with which -# offloaded ACS is used. -{% if 'n' in mode -%} -hw_mode=g -ieee80211n=1 -{% elif 'ac' in mode -%} -hw_mode=a -ieee80211h=1 -ieee80211ac=1 -{% else -%} -hw_mode={{ mode }} -{% endif %} -{% endif %} - -# ieee80211w: Whether management frame protection (MFP) is enabled -# 0 = disabled (default) -# 1 = optional -# 2 = required -{% if 'disabled' in mgmt_frame_protection -%} -ieee80211w=0 -{% elif 'optional' in mgmt_frame_protection -%} -ieee80211w=1 -{% elif 'required' in mgmt_frame_protection -%} -ieee80211w=2 -{% endif %} - -# ht_capab: HT capabilities (list of flags) -# LDPC coding capability: [LDPC] = supported -# Supported channel width set: [HT40-] = both 20 MHz and 40 MHz with secondary -# channel below the primary channel; [HT40+] = both 20 MHz and 40 MHz -# with secondary channel above the primary channel -# (20 MHz only if neither is set) -# Note: There are limits on which channels can be used with HT40- and -# HT40+. Following table shows the channels that may be available for -# HT40- and HT40+ use per IEEE 802.11n Annex J: -# freq HT40- HT40+ -# 2.4 GHz 5-13 1-7 (1-9 in Europe/Japan) -# 5 GHz 40,48,56,64 36,44,52,60 -# (depending on the location, not all of these channels may be available -# for use) -# Please note that 40 MHz channels may switch their primary and secondary -# channels if needed or creation of 40 MHz channel maybe rejected based -# on overlapping BSSes. These changes are done automatically when hostapd -# is setting up the 40 MHz channel. -# Spatial Multiplexing (SM) Power Save: [SMPS-STATIC] or [SMPS-DYNAMIC] -# (SMPS disabled if neither is set) -# HT-greenfield: [GF] (disabled if not set) -# Short GI for 20 MHz: [SHORT-GI-20] (disabled if not set) -# Short GI for 40 MHz: [SHORT-GI-40] (disabled if not set) -# Tx STBC: [TX-STBC] (disabled if not set) -# Rx STBC: [RX-STBC1] (one spatial stream), [RX-STBC12] (one or two spatial -# streams), or [RX-STBC123] (one, two, or three spatial streams); Rx STBC -# disabled if none of these set -# HT-delayed Block Ack: [DELAYED-BA] (disabled if not set) -# Maximum A-MSDU length: [MAX-AMSDU-7935] for 7935 octets (3839 octets if not -# set) -# DSSS/CCK Mode in 40 MHz: [DSSS_CCK-40] = allowed (not allowed if not set) -# 40 MHz intolerant [40-INTOLERANT] (not advertised if not set) -# L-SIG TXOP protection support: [LSIG-TXOP-PROT] (disabled if not set) -{% if cap_ht %} -ht_capab= -{%- endif -%} - -{%- if cap_ht_40mhz_incapable -%} -[40-INTOLERANT] -{%- endif -%} - -{%- if cap_ht_delayed_block_ack -%} -[DELAYED-BA] -{%- endif -%} - -{%- if cap_ht_dsss_cck_40 -%} -[DSSS_CCK-40] -{%- endif -%} - -{%- if cap_ht_greenfield -%} -[GF] -{%- endif -%} - -{%- if cap_ht_ldpc -%} -[LDPC] -{%- endif -%} - -{%- if cap_ht_lsig_protection -%} -[LSIG-TXOP-PROT] -{%- endif -%} - -{%- if cap_ht_max_amsdu -%} -[MAX-AMSDU-{{ cap_ht_max_amsdu }}] -{%- endif -%} - -{%- if cap_ht_smps -%} -[SMPS-{{ cap_ht_smps | upper }}] -{%- endif -%} - -{%- if cap_ht_chan_set_width -%} -{%- for csw in cap_ht_chan_set_width -%} -[{{ csw | upper }}] -{%- endfor -%} -{%- endif -%} - -{%- if cap_ht_short_gi -%} -{%- for gi in cap_ht_short_gi -%} -[SHORT-GI-{{ gi }}] -{%- endfor -%} -{%- endif -%} - -{%- if cap_ht_stbc_tx -%} -[TX-STBC] -{%- endif -%} -{%- if cap_ht_stbc_rx -%} -[RX-STBC{{ cap_ht_stbc_rx }}] -{%- endif %} - -# Required for full HT and VHT functionality -wme_enabled=1 - -{% if cap_ht_powersave -%} -# WMM-PS Unscheduled Automatic Power Save Delivery [U-APSD] -# Enable this flag if U-APSD supported outside hostapd (eg., Firmware/driver) -uapsd_advertisement_enabled=1 -{%- endif %} - -{% if cap_req_ht -%} -# Require stations to support HT PHY (reject association if they do not) -require_ht=1 -{% endif %} - -# vht_capab: VHT capabilities (list of flags) -# -# vht_max_mpdu_len: [MAX-MPDU-7991] [MAX-MPDU-11454] -# Indicates maximum MPDU length -# 0 = 3895 octets (default) -# 1 = 7991 octets -# 2 = 11454 octets -# 3 = reserved -# -# supported_chan_width: [VHT160] [VHT160-80PLUS80] -# Indicates supported Channel widths -# 0 = 160 MHz & 80+80 channel widths are not supported (default) -# 1 = 160 MHz channel width is supported -# 2 = 160 MHz & 80+80 channel widths are supported -# 3 = reserved -# -# Rx LDPC coding capability: [RXLDPC] -# Indicates support for receiving LDPC coded pkts -# 0 = Not supported (default) -# 1 = Supported -# -# Short GI for 80 MHz: [SHORT-GI-80] -# Indicates short GI support for reception of packets transmitted with TXVECTOR -# params format equal to VHT and CBW = 80Mhz -# 0 = Not supported (default) -# 1 = Supported -# -# Short GI for 160 MHz: [SHORT-GI-160] -# Indicates short GI support for reception of packets transmitted with TXVECTOR -# params format equal to VHT and CBW = 160Mhz -# 0 = Not supported (default) -# 1 = Supported -# -# Tx STBC: [TX-STBC-2BY1] -# Indicates support for the transmission of at least 2x1 STBC -# 0 = Not supported (default) -# 1 = Supported -# -# Rx STBC: [RX-STBC-1] [RX-STBC-12] [RX-STBC-123] [RX-STBC-1234] -# Indicates support for the reception of PPDUs using STBC -# 0 = Not supported (default) -# 1 = support of one spatial stream -# 2 = support of one and two spatial streams -# 3 = support of one, two and three spatial streams -# 4 = support of one, two, three and four spatial streams -# 5,6,7 = reserved -# -# SU Beamformer Capable: [SU-BEAMFORMER] -# Indicates support for operation as a single user beamformer -# 0 = Not supported (default) -# 1 = Supported -# -# SU Beamformee Capable: [SU-BEAMFORMEE] -# Indicates support for operation as a single user beamformee -# 0 = Not supported (default) -# 1 = Supported -# -# Compressed Steering Number of Beamformer Antennas Supported: -# [BF-ANTENNA-2] [BF-ANTENNA-3] [BF-ANTENNA-4] -# Beamformee's capability indicating the maximum number of beamformer -# antennas the beamformee can support when sending compressed beamforming -# feedback -# If SU beamformer capable, set to maximum value minus 1 -# else reserved (default) -# -# Number of Sounding Dimensions: -# [SOUNDING-DIMENSION-2] [SOUNDING-DIMENSION-3] [SOUNDING-DIMENSION-4] -# Beamformer's capability indicating the maximum value of the NUM_STS parameter -# in the TXVECTOR of a VHT NDP -# If SU beamformer capable, set to maximum value minus 1 -# else reserved (default) -# -# MU Beamformer Capable: [MU-BEAMFORMER] -# Indicates support for operation as an MU beamformer -# 0 = Not supported or sent by Non-AP STA (default) -# 1 = Supported -# -# VHT TXOP PS: [VHT-TXOP-PS] -# Indicates whether or not the AP supports VHT TXOP Power Save Mode -# or whether or not the STA is in VHT TXOP Power Save mode -# 0 = VHT AP doesn't support VHT TXOP PS mode (OR) VHT STA not in VHT TXOP PS -# mode -# 1 = VHT AP supports VHT TXOP PS mode (OR) VHT STA is in VHT TXOP power save -# mode -# -# +HTC-VHT Capable: [HTC-VHT] -# Indicates whether or not the STA supports receiving a VHT variant HT Control -# field. -# 0 = Not supported (default) -# 1 = supported -# -# Maximum A-MPDU Length Exponent: [MAX-A-MPDU-LEN-EXP0]..[MAX-A-MPDU-LEN-EXP7] -# Indicates the maximum length of A-MPDU pre-EOF padding that the STA can recv -# This field is an integer in the range of 0 to 7. -# The length defined by this field is equal to -# 2 pow(13 + Maximum A-MPDU Length Exponent) -1 octets -# -# VHT Link Adaptation Capable: [VHT-LINK-ADAPT2] [VHT-LINK-ADAPT3] -# Indicates whether or not the STA supports link adaptation using VHT variant -# HT Control field -# If +HTC-VHTcapable is 1 -# 0 = (no feedback) if the STA does not provide VHT MFB (default) -# 1 = reserved -# 2 = (Unsolicited) if the STA provides only unsolicited VHT MFB -# 3 = (Both) if the STA can provide VHT MFB in response to VHT MRQ and if the -# STA provides unsolicited VHT MFB -# Reserved if +HTC-VHTcapable is 0 -# -# Rx Antenna Pattern Consistency: [RX-ANTENNA-PATTERN] -# Indicates the possibility of Rx antenna pattern change -# 0 = Rx antenna pattern might change during the lifetime of an association -# 1 = Rx antenna pattern does not change during the lifetime of an association -# -# Tx Antenna Pattern Consistency: [TX-ANTENNA-PATTERN] -# Indicates the possibility of Tx antenna pattern change -# 0 = Tx antenna pattern might change during the lifetime of an association -# 1 = Tx antenna pattern does not change during the lifetime of an association -{% if cap_vht %} -vht_capab= -{%- endif -%} - -{%- if cap_vht_max_mpdu -%} -[MAX-MPDU-{{ cap_vht_max_mpdu }}] -{%- endif -%} - -{%- if cap_vht_max_mpdu_exp -%} -[MAX-A-MPDU-LEN-EXP{{ cap_vht_max_mpdu_exp }}] -{%- endif -%} - -{%- if cap_vht_chan_set_width -%} -[MAX-A-MPDU-LEN-EXP{{ cap_vht_max_mpdu_exp }}] -{%- endif -%} - -{%- if cap_vht_chan_set_width -%} -{%- if '2' in cap_vht_chan_set_width -%} -[VHT160] -{%- elif '3' in cap_vht_chan_set_width -%} -[VHT160-80PLUS80] -{%- endif -%} -{%- endif -%} - -{%- if cap_vht_stbc_tx -%} -[TX-STBC-2BY1] -{%- endif -%} - -{%- if cap_vht_stbc_rx -%} -[RX-STBC-{{ cap_vht_stbc_rx }}] -{%- endif -%} - -{%- if cap_vht_link_adaptation -%} -{%- if 'unsolicited' in cap_vht_link_adaptation -%} -[VHT-LINK-ADAPT2] -{%- elif 'both' in cap_vht_link_adaptation -%} -[VHT-LINK-ADAPT3] -{%- endif -%} -{%- endif -%} - -{%- if cap_vht_short_gi -%} -{%- for gi in cap_vht_short_gi -%} -[SHORT-GI-{{ gi }}] -{%- endfor -%} -{%- endif -%} - -{%- if cap_vht_ldpc -%} -[RXLDPC] -{%- endif -%} - -{%- if cap_vht_tx_powersave -%} -[VHT-TXOP-PS] -{%- endif -%} - -{%- if cap_vht_vht_cf -%} -[HTC-VHT] -{%- endif -%} - -{%- if cap_vht_beamform -%} -{%- for beamform in cap_vht_beamform -%} -{%- if 'single-user-beamformer' in beamform -%} -[SU-BEAMFORMER] -{%- elif 'single-user-beamformee' in beamform -%} -[SU-BEAMFORMEE] -{%- elif 'multi-user-beamformer' in beamform -%} -[MU-BEAMFORMER] -{%- elif 'multi-user-beamformee' in beamform -%} -[MU-BEAMFORMEE] -{%- endif -%} -{%- endfor -%} -{%- endif -%} - -{%- if cap_vht_antenna_fixed -%} -[RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] -{%- endif -%} - -{%- if cap_vht_antenna_cnt -%} -{%- for beamform in cap_vht_beamform -%} -{%- if 'single-user-beamformer' in beamform -%} -[BF-ANTENNA-{{ cap_vht_antenna_cnt|int -1 }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt|int -1}}] -{%- else -%} -[BF-ANTENNA-{{ cap_vht_antenna_cnt }}][SOUNDING-DIMENSION-{{ cap_vht_antenna_cnt }}] -{%- endif -%} -{%- endfor -%} -{%- endif %} - -# ieee80211n: Whether IEEE 802.11n (HT) is enabled -# 0 = disabled (default) -# 1 = enabled -# Note: You will also need to enable WMM for full HT functionality. -# Note: hw_mode=g (2.4 GHz) and hw_mode=a (5 GHz) is used to specify the band. -{% if cap_req_vht -%} -ieee80211n=0 -# Require stations to support VHT PHY (reject association if they do not) -require_vht=1 -{% endif %} - -{% if cap_vht_center_freq_1 -%} -# center freq = 5 GHz + (5 * index) -# So index 42 gives center freq 5.210 GHz -# which is channel 42 in 5G band -vht_oper_centr_freq_seg0_idx={{ cap_vht_center_freq_1 }} -{% endif %} - -{% if cap_vht_center_freq_2 -%} -# center freq = 5 GHz + (5 * index) -# So index 159 gives center freq 5.795 GHz -# which is channel 159 in 5G band -vht_oper_centr_freq_seg1_idx={{ cap_vht_center_freq_2 }} -{% endif %} - -{% if disable_broadcast_ssid -%} -# Send empty SSID in beacons and ignore probe request frames that do not -# specify full SSID, i.e., require stations to know SSID. -# default: disabled (0) -# 1 = send empty (length=0) SSID in beacon and ignore probe request for -# broadcast SSID -# 2 = clear SSID (ASCII 0), but keep the original length (this may be required -# with some clients that do not support empty SSID) and ignore probe -# requests for broadcast SSID -ignore_broadcast_ssid=1 -{% endif %} - -# Station MAC address -based authentication -# Please note that this kind of access control requires a driver that uses -# hostapd to take care of management frame processing and as such, this can be -# used with driver=hostap or driver=nl80211, but not with driver=atheros. -# 0 = accept unless in deny list -# 1 = deny unless in accept list -# 2 = use external RADIUS server (accept/deny lists are searched first) -macaddr_acl=0 - -{% if max_stations -%} -# Maximum number of stations allowed in station table. New stations will be -# rejected after the station table is full. IEEE 802.11 has a limit of 2007 -# different association IDs, so this number should not be larger than that. -# (default: 2007) -max_num_sta={{ max_stations }} -{% endif %} - -{% if isolate_stations -%} -# Client isolation can be used to prevent low-level bridging of frames between -# associated stations in the BSS. By default, this bridging is allowed. -ap_isolate=1 -{% endif %} - -{% if reduce_transmit_power -%} -# Add Power Constraint element to Beacon and Probe Response frames -# This config option adds Power Constraint element when applicable and Country -# element is added. Power Constraint element is required by Transmit Power -# Control. This can be used only with ieee80211d=1. -# Valid values are 0..255. -local_pwr_constraint={{ reduce_transmit_power }} -{% endif %} - -{% if expunge_failing_stations -%} -# Disassociate stations based on excessive transmission failures or other -# indications of connection loss. This depends on the driver capabilities and -# may not be available with all drivers. -disassoc_low_ack=1 -{% endif %} - -{% if sec_wep -%} -# IEEE 802.11 specifies two authentication algorithms. hostapd can be -# configured to allow both of these or only one. Open system authentication -# should be used with IEEE 802.1X. -# Bit fields of allowed authentication algorithms: -# bit 0 = Open System Authentication -# bit 1 = Shared Key Authentication (requires WEP) -auth_algs=2 - -# WEP rekeying (disabled if key lengths are not set or are set to 0) -# Key lengths for default/broadcast and individual/unicast keys: -# 5 = 40-bit WEP (also known as 64-bit WEP with 40 secret bits) -# 13 = 104-bit WEP (also known as 128-bit WEP with 104 secret bits) -wep_key_len_broadcast=5 -wep_key_len_unicast=5 - -# Static WEP key configuration -# -# The key number to use when transmitting. -# It must be between 0 and 3, and the corresponding key must be set. -# default: not set -wep_default_key=0 - -# The WEP keys to use. -# A key may be a quoted string or unquoted hexadecimal digits. -# The key length should be 5, 13, or 16 characters, or 10, 26, or 32 -# digits, depending on whether 40-bit (64-bit), 104-bit (128-bit), or -# 128-bit (152-bit) WEP is used. -# Only the default key must be supplied; the others are optional. -{% if sec_wep_key -%} -{% for key in sec_wep_key -%} -wep_key{{ loop.index -1 }}={{ key}} -{% endfor %} -{%- endif %} - -{% elif sec_wpa -%} -##### WPA/IEEE 802.11i configuration ########################################## - -# Enable WPA. Setting this variable configures the AP to require WPA (either -# WPA-PSK or WPA-RADIUS/EAP based on other configuration). For WPA-PSK, either -# wpa_psk or wpa_passphrase must be set and wpa_key_mgmt must include WPA-PSK. -# Instead of wpa_psk / wpa_passphrase, wpa_psk_radius might suffice. -# For WPA-RADIUS/EAP, ieee8021x must be set (but without dynamic WEP keys), -# RADIUS authentication server must be configured, and WPA-EAP must be included -# in wpa_key_mgmt. -# This field is a bit field that can be used to enable WPA (IEEE 802.11i/D3.0) -# and/or WPA2 (full IEEE 802.11i/RSN): -# bit0 = WPA -# bit1 = IEEE 802.11i/RSN (WPA2) (dot11RSNAEnabled) -{% if 'both' in sec_wpa_mode -%} -wpa=3 -{%- elif 'wpa2' in sec_wpa_mode -%} -wpa=2 -{%- elif 'wpa' in sec_wpa_mode -%} -wpa=1 -{%- endif %} - -{% if sec_wpa_cipher -%} -# Set of accepted cipher suites (encryption algorithms) for pairwise keys -# (unicast packets). This is a space separated list of algorithms: -# CCMP = AES in Counter mode with CBC-MAC (CCMP-128) -# TKIP = Temporal Key Integrity Protocol -# CCMP-256 = AES in Counter mode with CBC-MAC with 256-bit key -# GCMP = Galois/counter mode protocol (GCMP-128) -# GCMP-256 = Galois/counter mode protocol with 256-bit key -# Group cipher suite (encryption algorithm for broadcast and multicast frames) -# is automatically selected based on this configuration. If only CCMP is -# allowed as the pairwise cipher, group cipher will also be CCMP. Otherwise, -# TKIP will be used as the group cipher. The optional group_cipher parameter can -# be used to override this automatic selection. -{% if 'wpa2' in sec_wpa_mode -%} -# Pairwise cipher for RSN/WPA2 (default: use wpa_pairwise value) -rsn_pairwise={{ sec_wpa_cipher | join(" ") }} -{% else -%} -# Pairwise cipher for WPA (v1) (default: TKIP) -wpa_pairwise={{ sec_wpa_cipher | join(" ") }} -{%- endif -%} -{% endif %} - -{% if sec_wpa_passphrase -%} -# IEEE 802.11 specifies two authentication algorithms. hostapd can be -# configured to allow both of these or only one. Open system authentication -# should be used with IEEE 802.1X. -# Bit fields of allowed authentication algorithms: -# bit 0 = Open System Authentication -# bit 1 = Shared Key Authentication (requires WEP) -auth_algs=1 - -# WPA pre-shared keys for WPA-PSK. This can be either entered as a 256-bit -# secret in hex format (64 hex digits), wpa_psk, or as an ASCII passphrase -# (8..63 characters) that will be converted to PSK. This conversion uses SSID -# so the PSK changes when ASCII passphrase is used and the SSID is changed. -wpa_passphrase={{ sec_wpa_passphrase }} - -# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be -# added to enable SHA256-based stronger algorithms. -# WPA-PSK = WPA-Personal / WPA2-Personal -# WPA-PSK-SHA256 = WPA2-Personal using SHA256 -wpa_key_mgmt=WPA-PSK - -{% elif sec_wpa_radius -%} -##### IEEE 802.1X-2004 related configuration ################################## -# Require IEEE 802.1X authorization -ieee8021x=1 - -# Set of accepted key management algorithms (WPA-PSK, WPA-EAP, or both). The -# entries are separated with a space. WPA-PSK-SHA256 and WPA-EAP-SHA256 can be -# added to enable SHA256-based stronger algorithms. -# WPA-EAP = WPA-Enterprise / WPA2-Enterprise -# WPA-EAP-SHA256 = WPA2-Enterprise using SHA256 -wpa_key_mgmt=WPA-EAP - -{% if sec_wpa_radius_source -%} -# RADIUS client forced local IP address for the access point -# Normally the local IP address is determined automatically based on configured -# IP addresses, but this field can be used to force a specific address to be -# used, e.g., when the device has multiple IP addresses. -radius_client_addr={{ sec_wpa_radius_source }} - -# The own IP address of the access point (used as NAS-IP-Address) -own_ip_addr={{ sec_wpa_radius_source }} -{% else %} -# The own IP address of the access point (used as NAS-IP-Address) -own_ip_addr=127.0.0.1 -{% endif %} - -{% for radius in sec_wpa_radius -%} -{%- if not radius.disabled -%} -# RADIUS authentication server -auth_server_addr={{ radius.server }} -auth_server_port={{ radius.port }} -auth_server_shared_secret={{ radius.key }} -{% if radius.acc_port -%} -# RADIUS accounting server -acct_server_addr={{ radius.server }} -acct_server_port={{ radius.acc_port }} -acct_server_shared_secret={{ radius.key }} -{% endif %} -{% endif %} -{% endfor %} - -{% endif %} - -{% else %} -# Open system -auth_algs=1 -{% endif %} - -# TX queue parameters (EDCF / bursting) -# tx_queue_<queue name>_<param> -# queues: data0, data1, data2, data3 -# (data0 is the highest priority queue) -# parameters: -# aifs: AIFS (default 2) -# cwmin: cwMin (1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, -# 16383, 32767) -# cwmax: cwMax (same values as cwMin, cwMax >= cwMin) -# burst: maximum length (in milliseconds with precision of up to 0.1 ms) for -# bursting -# -# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): -# These parameters are used by the access point when transmitting frames -# to the clients. -# -# Low priority / AC_BK = background -tx_queue_data3_aifs=7 -tx_queue_data3_cwmin=15 -tx_queue_data3_cwmax=1023 -tx_queue_data3_burst=0 -# Note: for IEEE 802.11b mode: cWmin=31 cWmax=1023 burst=0 -# -# Normal priority / AC_BE = best effort -tx_queue_data2_aifs=3 -tx_queue_data2_cwmin=15 -tx_queue_data2_cwmax=63 -tx_queue_data2_burst=0 -# Note: for IEEE 802.11b mode: cWmin=31 cWmax=127 burst=0 -# -# High priority / AC_VI = video -tx_queue_data1_aifs=1 -tx_queue_data1_cwmin=7 -tx_queue_data1_cwmax=15 -tx_queue_data1_burst=3.0 -# Note: for IEEE 802.11b mode: cWmin=15 cWmax=31 burst=6.0 -# -# Highest priority / AC_VO = voice -tx_queue_data0_aifs=1 -tx_queue_data0_cwmin=3 -tx_queue_data0_cwmax=7 -tx_queue_data0_burst=1.5 - -# Default WMM parameters (IEEE 802.11 draft; 11-03-0504-03-000e): -# for 802.11a or 802.11g networks -# These parameters are sent to WMM clients when they associate. -# The parameters will be used by WMM clients for frames transmitted to the -# access point. -# -# note - txop_limit is in units of 32microseconds -# note - acm is admission control mandatory flag. 0 = admission control not -# required, 1 = mandatory -# note - Here cwMin and cmMax are in exponent form. The actual cw value used -# will be (2^n)-1 where n is the value given here. The allowed range for these -# wmm_ac_??_{cwmin,cwmax} is 0..15 with cwmax >= cwmin. -# -wmm_enabled=1 - -# Low priority / AC_BK = background -wmm_ac_bk_cwmin=4 -wmm_ac_bk_cwmax=10 -wmm_ac_bk_aifs=7 -wmm_ac_bk_txop_limit=0 -wmm_ac_bk_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=10 -# -# Normal priority / AC_BE = best effort -wmm_ac_be_aifs=3 -wmm_ac_be_cwmin=4 -wmm_ac_be_cwmax=10 -wmm_ac_be_txop_limit=0 -wmm_ac_be_acm=0 -# Note: for IEEE 802.11b mode: cWmin=5 cWmax=7 -# -# High priority / AC_VI = video -wmm_ac_vi_aifs=2 -wmm_ac_vi_cwmin=3 -wmm_ac_vi_cwmax=4 -wmm_ac_vi_txop_limit=94 -wmm_ac_vi_acm=0 -# Note: for IEEE 802.11b mode: cWmin=4 cWmax=5 txop_limit=188 -# -# Highest priority / AC_VO = voice -wmm_ac_vo_aifs=2 -wmm_ac_vo_cwmin=2 -wmm_ac_vo_cwmax=3 -wmm_ac_vo_txop_limit=47 -wmm_ac_vo_acm=0 - -""" - -# Please be careful if you edit the template. -config_wpa_suppl_tmpl = """ -# WPA supplicant config -network={ - ssid="{{ ssid }}" -{%- if sec_wpa_passphrase %} - psk="{{ sec_wpa_passphrase }}" -{% else %} - key_mgmt=NONE -{% endif %} -} - -""" - default_config_data = { 'address': [], 'address_remove': [], @@ -799,7 +62,7 @@ default_config_data = { 'cap_vht_center_freq_2' : '', 'cap_vht_chan_set_width' : '', 'cap_vht_ldpc' : False, - 'cap_vht_link_adaptation' : False, + 'cap_vht_link_adaptation' : '', 'cap_vht_max_mpdu_exp' : '', 'cap_vht_max_mpdu' : '', 'cap_vht_short_gi' : [], @@ -857,11 +120,8 @@ def get_conf_file(conf_type, intf): # create directory on demand if not os.path.exists(cfg_dir): os.mkdir(cfg_dir) - # fix permissions - corresponds to mode 755 - os.chmod(cfg_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) - uid = getpwnam(user).pw_uid - gid = getgrnam(group).gr_gid - os.chown(cfg_dir, uid, gid) + chmod_x(cfg_dir) + chown_file(cfg_dir, user, group) cfg_file = cfg_dir + r'/{}.cfg'.format(intf) return cfg_file @@ -872,11 +132,8 @@ def get_pid(conf_type, intf): # create directory on demand if not os.path.exists(cfg_dir): os.mkdir(cfg_dir) - # fix permissions - corresponds to mode 755 - os.chmod(cfg_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) - uid = getpwnam(user).pw_uid - gid = getgrnam(group).gr_gid - os.chown(cfg_dir, uid, gid) + chmod_x(cfg_dir) + chown_file(cfg_dir, user, group) cfg_file = cfg_dir + r'/{}.pid'.format(intf) return cfg_file @@ -888,11 +145,8 @@ def get_wpa_suppl_config_name(intf): # create directory on demand if not os.path.exists(cfg_dir): os.mkdir(cfg_dir) - # fix permissions - corresponds to mode 755 - os.chmod(cfg_dir, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) - uid = getpwnam(user).pw_uid - gid = getgrnam(group).gr_gid - os.chown(cfg_dir, uid, gid) + chmod_x(cfg_dir) + chown_file(cfg_dir, user, group) cfg_file = cfg_dir + r'/{}.cfg'.format(intf) return cfg_file @@ -1043,7 +297,7 @@ def get_config(): # VHT link adaptation capabilities if conf.exists('capabilities vht link-adaptation'): wifi['cap_vht'] = True - wifi['cap_vht_link_adaptation'] = True + wifi['cap_vht_link_adaptation'] = conf.return_value('capabilities vht link-adaptation') # Set the maximum length of A-MPDU pre-EOF padding that the station can receive if conf.exists('capabilities vht max-mpdu-exp'): @@ -1364,6 +618,11 @@ def verify(wifi): return None def generate(wifi): + # Prepare Jinja2 template loader from files + tmpl_path = os.path.join(vyos_data_dir["data"], "templates", "wifi") + fs_loader = FileSystemLoader(tmpl_path) + env = Environment(loader=fs_loader) + # always stop hostapd service first before reconfiguring it pidfile = get_pid('hostapd', wifi['intf']) if process_running(pidfile): @@ -1418,13 +677,13 @@ def generate(wifi): # render appropriate new config files depending on access-point or station mode if wifi['op_mode'] == 'ap': - tmpl = Template(config_hostapd_tmpl) + tmpl = env.get_template('hostapd.conf.tmpl') config_text = tmpl.render(wifi) with open(get_conf_file('hostapd', wifi['intf']), 'w') as f: f.write(config_text) elif wifi['op_mode'] == 'station': - tmpl = Template(config_wpa_suppl_tmpl) + tmpl = env.get_template('wpa_supplicant.conf.tmpl') config_text = tmpl.render(wifi) with open(get_conf_file('wpa_supplicant', wifi['intf']), 'w') as f: f.write(config_text) diff --git a/src/conf_mode/interfaces-wirelessmodem.py b/src/conf_mode/interfaces-wirelessmodem.py index d00259bf5..9b6de2d12 100755 --- a/src/conf_mode/interfaces-wirelessmodem.py +++ b/src/conf_mode/interfaces-wirelessmodem.py @@ -23,7 +23,7 @@ from netifaces import interfaces from vyos.config import Config from vyos.defaults import directories as vyos_data_dir -from vyos.util import chown_file, chmod_x_file, subprocess_cmd +from vyos.util import chown_file, chmod_x, subprocess_cmd from vyos import ConfigError default_config_data = { @@ -197,9 +197,9 @@ def generate(wwan): f.write(config_text) # make generated script file executable - chmod_x_file(script_wwan_pre_up) - chmod_x_file(script_wwan_ip_up) - chmod_x_file(script_wwan_ip_down) + chmod_x(script_wwan_pre_up) + chmod_x(script_wwan_ip_up) + chmod_x(script_wwan_ip_down) return None diff --git a/src/conf_mode/vrf.py b/src/conf_mode/vrf.py index a74b79317..53ee13bec 100755 --- a/src/conf_mode/vrf.py +++ b/src/conf_mode/vrf.py @@ -25,6 +25,7 @@ from subprocess import check_output, CalledProcessError from vyos.config import Config from vyos.configdict import list_diff from vyos.ifconfig import Interface +from vyos.util import read_file from vyos import ConfigError config_file = r'/etc/iproute2/rt_tables.d/vyos-vrf.conf' @@ -43,7 +44,7 @@ config_tmpl = """ """ default_config_data = { - 'bind_to_all': 0, + 'bind_to_all': '0', 'deleted': False, 'vrf_add': [], 'vrf_existing': [], @@ -103,7 +104,7 @@ def get_config(): # Should services be allowed to bind to all VRFs? if conf.exists(['bind-to-all']): - vrf_config['bind_to_all'] = 1 + vrf_config['bind_to_all'] = '1' # Determine vrf interfaces (currently effective) - to determine which # vrf interface is no longer present and needs to be removed @@ -210,12 +211,15 @@ def apply(vrf_config): # set the default VRF global behaviour bind_all = vrf_config['bind_to_all'] - _cmd(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}') - _cmd(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}') + if read_file('/proc/sys/net/ipv4/tcp_l3mdev_accept') != bind_all: + _cmd(f'sysctl -wq net.ipv4.tcp_l3mdev_accept={bind_all}') + _cmd(f'sysctl -wq net.ipv4.udp_l3mdev_accept={bind_all}') for vrf in vrf_config['vrf_remove']: name = vrf['name'] if os.path.isdir(f'/sys/class/net/{name}'): + _cmd(f'sudo ip -4 route del vrf {name} unreachable default metric 4278198272') + _cmd(f'sudo ip -6 route del vrf {name} unreachable default metric 4278198272') _cmd(f'ip link delete dev {name}') for vrf in vrf_config['vrf_add']: diff --git a/src/op_mode/show_openvpn.py b/src/op_mode/show_openvpn.py index 06b90296f..32918ddce 100755 --- a/src/op_mode/show_openvpn.py +++ b/src/op_mode/show_openvpn.py @@ -15,6 +15,7 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # +import os import jinja2 import argparse @@ -63,6 +64,9 @@ def get_status(mode, interface): 'clients': [], } + if not os.path.exists(status_file): + return data + with open(status_file, 'r') as f: lines = f.readlines() for line_no, line in enumerate(lines): diff --git a/src/op_mode/wireguard.py b/src/op_mode/wireguard.py index 512c80dda..c684f8a47 100755 --- a/src/op_mode/wireguard.py +++ b/src/op_mode/wireguard.py @@ -150,7 +150,7 @@ if __name__ == '__main__': if args.listkdir: list_key_dirs() if args.showinterface: - intf = WireGuardIf(args.showinterface, debug=False) + intf = WireGuardIf(args.showinterface, create=False, debug=False) intf.op_show_interface() if args.delkdir: if args.location: |