diff --git a/netifd/Makefile b/netifd/Makefile index 4b5f110da..2e64a6736 100644 --- a/netifd/Makefile +++ b/netifd/Makefile @@ -5,9 +5,9 @@ PKG_RELEASE:=1 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL=$(PROJECT_GIT)/project/netifd.git -PKG_SOURCE_DATE:=2021-07-26 -PKG_SOURCE_VERSION:=440eb0647708274cc8d7d9e7c2bb0cfdfba90023 -PKG_MIRROR_HASH:=eed957036ab608fdc49bdf801fc5b4405fcd2a3a5e5d3343ec39898e156c10e9 +PKG_SOURCE_DATE:=2021-01-09 +PKG_SOURCE_VERSION:=753c351bc729967a691d99e27693be5aec334028 +PKG_MIRROR_HASH:=e7d95bde520fc660d0a49e28c5bb50fff3071d7f48fe7fc3fc610f38edfc7df1 PKG_MAINTAINER:=Felix Fietkau PKG_LICENSE:=GPL-2.0 @@ -25,11 +25,6 @@ define Package/netifd TITLE:=OpenWrt Network Interface Configuration Daemon endef -define Package/netifd/conffiles -/etc/udhcpc.user -/etc/udhcpc.user.d/ -endef - TARGET_CFLAGS += \ -I$(STAGING_DIR)/usr/include/libnl-tiny \ -I$(STAGING_DIR)/usr/include \ @@ -45,7 +40,6 @@ define Package/netifd/install $(INSTALL_DIR) $(1)/sbin $(INSTALL_BIN) $(PKG_BUILD_DIR)/netifd $(1)/sbin/ $(CP) ./files/* $(1)/ - $(INSTALL_DIR) $(1)/etc/udhcpc.user.d/ $(CP) $(PKG_BUILD_DIR)/scripts/* $(1)/lib/netifd/ endef diff --git a/netifd/files/etc/hotplug.d/net/20-smp-packet-steering b/netifd/files/etc/hotplug.d/net/20-smp-tune similarity index 72% rename from netifd/files/etc/hotplug.d/net/20-smp-packet-steering rename to netifd/files/etc/hotplug.d/net/20-smp-tune index 8a86bf75f..8932a9c07 100644 --- a/netifd/files/etc/hotplug.d/net/20-smp-packet-steering +++ b/netifd/files/etc/hotplug.d/net/20-smp-tune @@ -14,7 +14,7 @@ find_irq_cpu() { [ -n "$match" ] && { set -- $match shift - for cur in $(seq 1 $NPROCS); do + for cur in `seq 1 $NPROCS`; do [ "$1" -gt 0 ] && { cpu=$(($cur - 1)) break @@ -34,8 +34,8 @@ set_hex_val() { echo "$val" > "$file" } -packet_steering="$(uci get "network.@globals[0].packet_steering")" -[ "$packet_steering" != 1 ] && exit 0 +default_ps="$(uci get "network.@globals[0].default_ps")" +[ -z "$default_ps" -o "$default_ps" == 0 ] && exit 0 exec 512>/var/lock/smp_tune.lock flock 512 || exit 1 @@ -52,16 +52,16 @@ for dev in /sys/class/net/*; do irq_cpu="$(find_irq_cpu "$device")" irq_cpu_mask="$((1 << $irq_cpu))" - for q in ${dev}/queues/tx-*; do - set_hex_val "$q/xps_cpus" "$PROC_MASK" + for q in ${dev}/queues/rx-*; do + set_hex_val "$q/rps_cpus" "$(($PROC_MASK & ~$irq_cpu_mask))" done - # ignore dsa slave ports for RPS - subsys="$(readlink "${dev}/device/subsystem")" - subsys="$(basename "$subsys")" - [ "$subsys" = "mdio_bus" ] && continue + ntxq="$(ls -d ${dev}/queues/tx-* | wc -l)" - for q in ${dev}/queues/rx-*; do - set_hex_val "$q/rps_cpus" "$PROC_MASK" + idx=$(($irq_cpu + 1)) + for q in ${dev}/queues/tx-*; do + set_hex_val "$q/xps_cpus" "$((1 << $idx))" + let "idx = idx + 1" + [ "$idx" -ge "$NPROCS" ] && idx=0 done done diff --git a/netifd/files/etc/init.d/network b/netifd/files/etc/init.d/network index dc208c4ce..668ab590f 100755 --- a/netifd/files/etc/init.d/network +++ b/netifd/files/etc/init.d/network @@ -17,6 +17,7 @@ start_service() { procd_open_instance procd_set_param command /sbin/netifd + #procd_set_param limits core="unlimited" procd_set_param respawn procd_set_param watch network.interface [ -e /proc/sys/kernel/core_pattern ] && { @@ -40,6 +41,11 @@ stop_service() { sleep 1 } +service_running() { + ubus -t 30 wait_for network.interface + /sbin/wifi reload_legacy +} + validate_atm_bridge_section() { uci_validate_section network "atm-bridge" "${1}" \ diff --git a/netifd/files/etc/uci-defaults/14_migrate-dhcp-release b/netifd/files/etc/uci-defaults/14_migrate-dhcp-release deleted file mode 100644 index f1b384eec..000000000 --- a/netifd/files/etc/uci-defaults/14_migrate-dhcp-release +++ /dev/null @@ -1,23 +0,0 @@ -. /lib/functions.sh - -migrate_release() { - local config="$1" - local proto - local release - - config_get proto "$config" proto - config_get release "$config" release - - [ "$proto" = "dhcp" ] && [ -n "$release" ] && { - norelease="$((!$release))" - uci_set network "$config" norelease "$norelease" - uci_remove network "$config" release - } - -} - -config_load network -config_foreach migrate_release interface -uci commit network - -exit 0 diff --git a/netifd/files/etc/udhcpc.user b/netifd/files/etc/udhcpc.user deleted file mode 100644 index 78e2ba5f1..000000000 --- a/netifd/files/etc/udhcpc.user +++ /dev/null @@ -1 +0,0 @@ -# This script is sourced by udhcpc's dhcp.script at every DHCP event. diff --git a/netifd/files/lib/netifd/dhcp.script b/netifd/files/lib/netifd/dhcp.script index c857c9fc0..00604f40e 100755 --- a/netifd/files/lib/netifd/dhcp.script +++ b/netifd/files/lib/netifd/dhcp.script @@ -13,7 +13,7 @@ set_classless_routes() { done } -setup_interface() { +setup_interface () { proto_init_update "*" 1 proto_add_ipv4_address "$ip" "${subnet:-255.255.255.0}" # TODO: apply $broadcast @@ -27,7 +27,6 @@ setup_interface() { eval "$(ipcalc.sh "$i/$mask")";gw_net="$NETWORK" [ "$ip_net" != "$gw_net" ] && proto_add_ipv4_route "$i" 32 "" "$ip" - #[ "$DEFAULTROUTE" = 0 ] || proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" proto_add_ipv4_route 0.0.0.0 0 "$i" "$ip" local r @@ -47,16 +46,10 @@ setup_interface() { proto_add_dns_search "$i" done - # TODO: Deprecate timesvr in favor of timesrv - if [ -n "$timesvr" -a -z "$timesrv" ]; then - timesrv="$timesvr" - echo "Environment variable 'timesvr' will be deprecated; use 'timesrv' instead." - fi - proto_add_data [ -n "$ZONE" ] && json_add_string zone "$ZONE" [ -n "$ntpsrv" ] && json_add_string ntpserver "$ntpsrv" - [ -n "$timesrv" ] && json_add_string timeserver "$timesrv" + [ -n "$timesvr" ] && json_add_string timeserver "$timesvr" [ -n "$hostname" ] && json_add_string hostname "$hostname" [ -n "$message" ] && json_add_string message "$message" [ -n "$timezone" ] && json_add_int timezone "$timezone" @@ -113,8 +106,5 @@ esac # user rules [ -f /etc/udhcpc.user ] && . /etc/udhcpc.user "$@" -for f in /etc/udhcpc.user.d/*; do - [ -f "$f" ] && (. "$f" "$@") -done exit 0 diff --git a/netifd/files/lib/netifd/proto/dhcp.sh b/netifd/files/lib/netifd/proto/dhcp.sh index 8db848260..0d06eba06 100755 --- a/netifd/files/lib/netifd/proto/dhcp.sh +++ b/netifd/files/lib/netifd/proto/dhcp.sh @@ -14,7 +14,7 @@ proto_dhcp_init_config() { proto_config_add_string clientid proto_config_add_string vendorid proto_config_add_boolean 'broadcast:bool' - proto_config_add_boolean 'norelease:bool' + proto_config_add_boolean 'release:bool' proto_config_add_string 'reqopts:list(string)' proto_config_add_boolean 'defaultreqopts:bool' proto_config_add_string iface6rd @@ -35,8 +35,8 @@ proto_dhcp_setup() { local config="$1" local iface="$2" - local ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute - json_get_vars ipaddr hostname clientid vendorid broadcast norelease reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute defaultroute + local ipaddr hostname clientid vendorid broadcast release reqopts defaultreqopts iface6rd sendopts delegate zone6rd zone mtu6rd customroutes classlessroute + json_get_vars ipaddr hostname clientid vendorid broadcast release reqopts defaultreqopts iface6rd delegate zone6rd zone mtu6rd customroutes classlessroute local opt dhcpopts for opt in $reqopts; do @@ -50,7 +50,7 @@ proto_dhcp_setup() { [ "$defaultreqopts" = 0 ] && defaultreqopts="-o" || defaultreqopts= [ "$broadcast" = 1 ] && broadcast="-B" || broadcast= - [ "$norelease" = 1 ] && norelease="" || norelease="-R" + [ "$release" = 1 ] && release="-R" || release= [ -n "$clientid" ] && clientid="-x 0x3d:${clientid//:/}" || clientid="-C" [ -n "$iface6rd" ] && proto_export "IFACE6RD=$iface6rd" [ "$iface6rd" != 0 -a -f /lib/netifd/proto/6rd.sh ] && append dhcpopts "-O 212" @@ -58,7 +58,6 @@ proto_dhcp_setup() { [ -n "$zone" ] && proto_export "ZONE=$zone" [ -n "$mtu6rd" ] && proto_export "MTU6RD=$mtu6rd" [ -n "$customroutes" ] && proto_export "CUSTOMROUTES=$customroutes" - [ -n "$defaultroute" ] && proto_export "DEFAULTROUTE=$defaultroute" [ "$delegate" = "0" ] && proto_export "IFACE6RD_DELEGATE=0" # Request classless route option (see RFC 3442) by default [ "$classlessroute" = "0" ] || append dhcpopts "-O 121" @@ -71,7 +70,7 @@ proto_dhcp_setup() { ${ipaddr:+-r $ipaddr} \ ${hostname:+-x "hostname:$hostname"} \ ${vendorid:+-V "$vendorid"} \ - $clientid $defaultreqopts $broadcast $norelease $dhcpopts + $clientid $defaultreqopts $broadcast $release $dhcpopts } proto_dhcp_renew() { diff --git a/netifd/files/lib/network/config.sh b/netifd/files/lib/network/config.sh index 4cd28e4ce..0ded45edc 100755 --- a/netifd/files/lib/network/config.sh +++ b/netifd/files/lib/network/config.sh @@ -6,13 +6,13 @@ find_config() { local device="$1" local ifdev ifl3dev ifobj - for ifobj in $(ubus list network.interface.\*); do + for ifobj in `ubus list network.interface.\*`; do interface="${ifobj##network.interface.}" ( json_load "$(ifstatus $interface)" json_get_var ifdev device json_get_var ifl3dev l3_device - if [ "$device" = "$ifdev" ] || [ "$device" = "$ifl3dev" ]; then + if [[ "$device" = "$ifdev" ]] || [[ "$device" = "$ifl3dev" ]]; then echo "$interface" exit 0 else diff --git a/netifd/files/sbin/ifup b/netifd/files/sbin/ifup index 15be535bb..5515b91f7 100755 --- a/netifd/files/sbin/ifup +++ b/netifd/files/sbin/ifup @@ -37,7 +37,7 @@ done [ "$modes" = "down up" ] && ubus call network reload if [ -n "$ifup_all" ]; then - for interface in $(ubus -S list 'network.interface.*'); do + for interface in `ubus -S list 'network.interface.*'`; do if_call "${interface##network.interface.}" done [ -n "$setup_wifi" ] && /sbin/wifi up diff --git a/netifd/files/usr/share/udhcpc/default.script b/netifd/files/usr/share/udhcpc/default.script index 0a9eb0180..ac765a636 100755 --- a/netifd/files/usr/share/udhcpc/default.script +++ b/netifd/files/usr/share/udhcpc/default.script @@ -14,8 +14,8 @@ set_classless_routes() { } setup_interface() { - echo "udhcpc: ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface" - ip addr add $ip/${subnet:-255.255.255.0} broadcast ${broadcast:-+} dev $interface + echo "udhcpc: ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+}" + ifconfig $interface $ip netmask ${subnet:-255.255.255.0} broadcast ${broadcast:-+} [ -n "$router" ] && [ "$router" != "0.0.0.0" ] && [ "$router" != "255.255.255.255" ] && { echo "udhcpc: setting default routers: $router" @@ -41,7 +41,7 @@ setup_interface() { applied= case "$1" in deconfig) - ip -4 addr flush dev "$interface" + ifconfig "$interface" 0.0.0.0 ;; renew) setup_interface update diff --git a/netifd/patches/002-Fix-wep-mixed-mode-configuration.patch b/netifd/patches/002-Fix-wep-mixed-mode-configuration.patch new file mode 100644 index 000000000..a0caabd00 --- /dev/null +++ b/netifd/patches/002-Fix-wep-mixed-mode-configuration.patch @@ -0,0 +1,13 @@ +diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh +index 8c0ff78..aaa3a1c 100644 +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -235,6 +235,8 @@ wireless_vif_parse_encryption() { + ;; + *wep*) + auth_type=wep ++ wpa=0 ++ wpa_pairwise= + case "$encryption" in + *shared*) + auth_mode_open=0 diff --git a/netifd/patches/003-Dont-allow-standalone-TKIP.patch b/netifd/patches/003-Dont-allow-standalone-TKIP.patch new file mode 100644 index 000000000..f4a7d3e3a --- /dev/null +++ b/netifd/patches/003-Dont-allow-standalone-TKIP.patch @@ -0,0 +1,66 @@ +diff -Nur a/scripts/netifd-wireless.sh netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh +--- a/scripts/netifd-wireless.sh 2020-05-01 14:46:21.243721221 -0700 ++++ netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh 2020-05-01 14:47:21.139395257 -0700 +@@ -42,7 +42,6 @@ + json_get_vars channel hwmode + + auto_channel=0 +- enable_ht=0 + htmode= + hwmode="${hwmode##11}" + hwmode_n="${hwmode##n}" +@@ -59,7 +58,6 @@ + esac + + [[ "$hwmode_n" = "$hwmode" ]] || { +- enable_ht=1 + hwmode="$hwmode_n" + + json_get_vars htmode +@@ -195,16 +193,17 @@ + auth_mode_open=1 + auth_mode_shared=0 + auth_type=none +- wpa_cipher=CCMP ++ wpa=0 ++ wpa_cipher= + case "$encryption" in + *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";; +- *aes|*ccmp) wpa_cipher="CCMP";; +- *tkip) wpa_cipher="TKIP";; ++ *aes|*ccmp| psk2 | wpa2) wpa_cipher="CCMP";; ++ *tkip | wpa | psk ) wpa_cipher="TKIP";; + *gcmp) wpa_cipher="GCMP";; + esac + +- # 802.11n requires CCMP for WPA +- [ "$enable_ht:$wpa_cipher" = "1:TKIP" ] && wpa_cipher="CCMP TKIP" ++ # Standlone TKIP is no longer allowed ++ [ "$wpa_cipher" = "TKIP" ] && wpa_cipher="CCMP TKIP" + + # Examples: + # psk-mixed/tkip => WPA1+2 PSK, TKIP +@@ -212,6 +211,10 @@ + # wpa2/tkip+aes => WPA2 RADIUS, CCMP+TKIP + + case "$encryption" in ++ none) ++ wpa=0 ++ wpa_cipher= ++ ;; + wpa2*|wpa3*|*psk2*|psk3*|sae*|owe*) + wpa=2 + ;; +@@ -222,8 +225,10 @@ + wpa=1 + ;; + *) +- wpa=0 +- wpa_cipher= ++ # TKIP alone is now prohibited by WFA so the only ++ # combination left must be CCMP+TKIP (wpa=3) ++ wpa=3 ++ wpa_cipher="CCMP TKIP" + ;; + esac + wpa_pairwise="$wpa_cipher" diff --git a/netifd/patches/004-Fix-regression-in-enabling-ht-mode.patch b/netifd/patches/004-Fix-regression-in-enabling-ht-mode.patch new file mode 100644 index 000000000..d6328cfa3 --- /dev/null +++ b/netifd/patches/004-Fix-regression-in-enabling-ht-mode.patch @@ -0,0 +1,20 @@ +diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh +index e30aeec..09ac4ab 100644 +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -42,6 +42,7 @@ _wdev_prepare_channel() { + json_get_vars channel hwmode + + auto_channel=0 ++ enable_ht=0 + htmode= + hwmode="${hwmode##11}" + hwmode_n="${hwmode##n}" +@@ -58,6 +59,7 @@ _wdev_prepare_channel() { + esac + + [[ "$hwmode_n" = "$hwmode" ]] || { ++ enable_ht=1 + hwmode="$hwmode_n" + + json_get_vars htmode diff --git a/netifd/patches/005-Fix-8021x-configuration.patch b/netifd/patches/005-Fix-8021x-configuration.patch new file mode 100644 index 000000000..f21c848ef --- /dev/null +++ b/netifd/patches/005-Fix-8021x-configuration.patch @@ -0,0 +1,35 @@ +diff -Nur a/scripts/netifd-wireless.sh netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh +--- a/scripts/netifd-wireless.sh 2020-05-01 14:55:34.404718599 -0700 ++++ netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh 2020-05-01 15:00:20.171171673 -0700 +@@ -204,9 +204,6 @@ + *gcmp) wpa_cipher="GCMP";; + esac + +- # Standlone TKIP is no longer allowed +- [ "$wpa_cipher" = "TKIP" ] && wpa_cipher="CCMP TKIP" +- + # Examples: + # psk-mixed/tkip => WPA1+2 PSK, TKIP + # wpa-psk2/tkip+aes => WPA2 PSK, CCMP+TKIP +@@ -227,12 +224,17 @@ + wpa=1 + ;; + *) +- # TKIP alone is now prohibited by WFA so the only +- # combination left must be CCMP+TKIP (wpa=3) +- wpa=3 +- wpa_cipher="CCMP TKIP" ++ wpa=0 ++ wpa_cipher= + ;; + esac ++ # Standlone TKIP is no longer allowed ++ # TKIP alone is now prohibited by WFA so the only ++ # combination left must be CCMP+TKIP (wpa=3) ++ [ "$wpa_pairwise" = "TKIP" ] && { ++ wpa=3 ++ wpa_cipher="CCMP TKIP" ++ } + wpa_pairwise="$wpa_cipher" + + case "$encryption" in diff --git a/netifd/patches/006-Fix-8021x-authentication.patch b/netifd/patches/006-Fix-8021x-authentication.patch new file mode 100644 index 000000000..18bc22069 --- /dev/null +++ b/netifd/patches/006-Fix-8021x-authentication.patch @@ -0,0 +1,28 @@ +diff -Nur a/scripts/netifd-wireless.sh netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh +--- a/scripts/netifd-wireless.sh 2020-05-01 15:05:45.809410514 -0700 ++++ netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh 2020-05-01 15:08:44.124446556 -0700 +@@ -197,6 +197,8 @@ + auth_type=none + wpa=0 + wpa_cipher= ++ eapol_key_index_workaround=0 ++ + case "$encryption" in + *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";; + *aes|*ccmp| psk2 | wpa2) wpa_cipher="CCMP";; +@@ -256,8 +258,14 @@ + *psk*) + auth_type=psk + ;; +- *wpa*|*8021x*) ++ *wpa*) ++ auth_type=eap ++ eapol_key_index_workaround=1 ++ ;; ++ *8021x*) + auth_type=eap ++ eapol_version=2 ++ eap_server=0 + ;; + *wep*) + auth_type=wep diff --git a/netifd/patches/010-add-link-aggregation-support.patch b/netifd/patches/010-add-link-aggregation-support.patch new file mode 100644 index 000000000..2b7b1e628 --- /dev/null +++ b/netifd/patches/010-add-link-aggregation-support.patch @@ -0,0 +1,865 @@ +diff -Nur a/bonding.c netifd-2019-08-05-5e02f944/bonding.c +--- a/bonding.c 1969-12-31 16:00:00.000000000 -0800 ++++ netifd-2019-08-05-5e02f944/bonding.c 2020-05-01 16:08:30.225672306 -0700 +@@ -0,0 +1,547 @@ ++/* ++ * netifd - network interface daemon ++ * Copyright (c) 2013 The Linux Foundation. All rights reserved. ++ * Copyright (C) 2012 Felix Fietkau ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 ++ * 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. ++ */ ++#include ++#include ++#include ++#include ++#include ++ ++#include "netifd.h" ++#include "device.h" ++#include "interface.h" ++#include "system.h" ++ ++enum { ++ BONDING_ATTR_IFNAME, ++ BONDING_ATTR_SLAVES, ++ BONDING_ATTR_MODE, ++ BONDING_ATTR_XMITHASHPOL, ++ __BONDING_ATTR_MAX ++}; ++ ++static const struct blobmsg_policy bonding_attrs[__BONDING_ATTR_MAX] = { ++ [BONDING_ATTR_IFNAME] = { "ifname", BLOBMSG_TYPE_STRING }, ++ [BONDING_ATTR_SLAVES] = { "slaves", BLOBMSG_TYPE_ARRAY }, ++ [BONDING_ATTR_MODE] = { "mode", BLOBMSG_TYPE_INT32 }, ++ [BONDING_ATTR_XMITHASHPOL] = { "xmit_hash_policy", BLOBMSG_TYPE_STRING }, ++}; ++ ++static const struct uci_blob_param_info bonding_attr_info[__BONDING_ATTR_MAX] = { ++ [BONDING_ATTR_SLAVES] = { .type = BLOBMSG_TYPE_STRING }, ++}; ++ ++static const struct uci_blob_param_list bonding_attr_list = { ++ .n_params = __BONDING_ATTR_MAX, ++ .params = bonding_attrs, ++ .info = bonding_attr_info, ++ ++ .n_next = 1, ++ .next = { &device_attr_list }, ++}; ++ ++static struct device *bonding_create(const char *name, struct device_type *devtype, struct blob_attr *attr); ++static void bonding_config_init(struct device *dev); ++static void bonding_free(struct device *dev); ++static void bonding_dump_info(struct device *dev, struct blob_buf *b); ++enum dev_change_type ++bonding_reload(struct device *dev, struct blob_attr *attr); ++ ++struct device_type bonding_device_type = { ++ .name = "Bonding", ++ .config_params = &bonding_attr_list, ++ ++ .create = bonding_create, ++ .config_init = bonding_config_init, ++ .reload = bonding_reload, ++ .free = bonding_free, ++ .dump_info = bonding_dump_info, ++}; ++ ++struct bonding_state { ++ struct device dev; ++ device_state_cb set_state; ++ ++ struct blob_attr *config_data; ++ struct bonding_config config; ++ struct blob_attr *ifnames; ++ bool active; ++ bool force_active; ++ ++ struct bonding_member *primary_port; ++ struct vlist_tree members; ++ int n_present; ++}; ++ ++struct bonding_member { ++ struct vlist_node node; ++ struct bonding_state *bst; ++ struct device_user dev; ++ bool present; ++ char name[]; ++}; ++ ++static void ++bonding_reset_primary(struct bonding_state *bst) ++{ ++ struct bonding_member *bm; ++ ++ if (!bst->primary_port && ++ (bst->dev.settings.flags & DEV_OPT_MACADDR)) ++ return; ++ ++ bst->primary_port = NULL; ++ bst->dev.settings.flags &= ~DEV_OPT_MACADDR; ++ vlist_for_each_element(&bst->members, bm, node) { ++ uint8_t *macaddr; ++ ++ if (!bm->present) ++ continue; ++ ++ bst->primary_port = bm; ++ if (bm->dev.dev->settings.flags & DEV_OPT_MACADDR) ++ macaddr = bm->dev.dev->settings.macaddr; ++ else ++ macaddr = bm->dev.dev->orig_settings.macaddr; ++ memcpy(bst->dev.settings.macaddr, macaddr, 6); ++ bst->dev.settings.flags |= DEV_OPT_MACADDR; ++ return; ++ } ++} ++ ++static int ++bonding_disable_member(struct bonding_member *bm) ++{ ++ struct bonding_state *bst = bm->bst; ++ ++ if (!bm->present) ++ return 0; ++ ++ system_bonding_delif(&bst->dev, bm->dev.dev); ++ device_release(&bm->dev); ++ ++ return 0; ++} ++ ++static int ++bonding_enable_member(struct bonding_member *bm) ++{ ++ struct bonding_state *bst = bm->bst; ++ int ret; ++ ++ if (!bm->present) ++ return 0; ++ ++ ret = device_claim(&bm->dev); ++ if (ret < 0) ++ goto error; ++ ++ ret = system_bonding_addif(&bst->dev, bm->dev.dev); ++ if (ret < 0) { ++ D(DEVICE, "Bridge device %s could not be added\n", bm->dev.dev->ifname); ++ goto error; ++ } ++ ++ return 0; ++ ++error: ++ bm->present = false; ++ bst->n_present--; ++ return ret; ++} ++ ++static void ++bonding_remove_member(struct bonding_member *bm) ++{ ++ struct bonding_state *bst = bm->bst; ++ ++ if (!bm->present) ++ return; ++ ++ if (bm == bst->primary_port) ++ bonding_reset_primary(bst); ++ ++ if (bst->dev.active) ++ bonding_disable_member(bm); ++ ++ bm->present = false; ++ bm->bst->n_present--; ++ ++ bst->force_active = false; ++ if (bst->n_present == 0) ++ device_set_present(&bst->dev, false); ++} ++ ++static void ++bonding_free_member(struct bonding_member *bm) ++{ ++ struct device *dev = bm->dev.dev; ++ ++ bonding_remove_member(bm); ++ device_remove_user(&bm->dev); ++ ++ /* ++ * When reloading the config and moving a device from one bonding to ++ * another, the other bonding may have tried to claim this device ++ * before it was removed here. ++ * Ensure that claiming the device is retried by toggling its present ++ * state ++ */ ++ if (dev->present) { ++ device_set_present(dev, false); ++ device_set_present(dev, true); ++ } ++ ++ free(bm); ++} ++ ++static void ++bonding_member_cb(struct device_user *dev, enum device_event ev) ++{ ++ struct bonding_member *bm = container_of(dev, struct bonding_member, dev); ++ struct bonding_state *bst = bm->bst; ++ ++ switch (ev) { ++ case DEV_EVENT_ADD: ++ assert(!bm->present); ++ ++ bm->present = true; ++ bst->n_present++; ++ ++ if (bst->dev.active) ++ bonding_enable_member(bm); ++ else if (bst->n_present == 1) ++ device_set_present(&bst->dev, true); ++ ++ break; ++ case DEV_EVENT_REMOVE: ++ if (dev->hotplug) { ++ vlist_delete(&bst->members, &bm->node); ++ return; ++ } ++ ++ if (bm->present) ++ bonding_remove_member(bm); ++ ++ break; ++ default: ++ return; ++ } ++} ++ ++static int ++bonding_set_down(struct bonding_state *bst) ++{ ++ struct bonding_member *bm; ++ ++ bst->set_state(&bst->dev, false); ++ ++ vlist_for_each_element(&bst->members, bm, node) ++ bonding_disable_member(bm); ++ ++ system_bonding_delbonding(&bst->dev); ++ ++ return 0; ++} ++ ++static int ++bonding_set_up(struct bonding_state *bst) ++{ ++ struct bonding_member *bm; ++ int ret; ++ ++ if (!bst->force_active && !bst->n_present) ++ return -ENOENT; ++ ++ ret = system_bonding_addbonding(&bst->dev, &bst->config); ++ if (ret < 0) ++ goto out; ++ ++ vlist_for_each_element(&bst->members, bm, node) ++ bonding_enable_member(bm); ++ ++ if (!bst->force_active && !bst->n_present) { ++ /* initialization of all member interfaces failed */ ++ system_bonding_delbonding(&bst->dev); ++ device_set_present(&bst->dev, false); ++ return -ENOENT; ++ } ++ ++ bonding_reset_primary(bst); ++ ret = bst->set_state(&bst->dev, true); ++ if (ret < 0) ++ bonding_set_down(bst); ++ ++out: ++ return ret; ++} ++ ++static int ++bonding_set_state(struct device *dev, bool up) ++{ ++ struct bonding_state *bst; ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ ++ if (up) ++ return bonding_set_up(bst); ++ else ++ return bonding_set_down(bst); ++} ++ ++static struct bonding_member * ++bonding_create_member(struct bonding_state *bst, struct device *dev, bool hotplug) ++{ ++ struct bonding_member *bm; ++ ++ bm = calloc(1, sizeof(*bm) + strlen(dev->ifname) + 1); ++ bm->bst = bst; ++ bm->dev.cb = bonding_member_cb; ++ bm->dev.hotplug = hotplug; ++ strcpy(bm->name, dev->ifname); ++ bm->dev.dev = dev; ++ vlist_add(&bst->members, &bm->node, bm->name); ++ if (hotplug) ++ bm->node.version = -1; ++ ++ return bm; ++} ++ ++static void ++bonding_member_update(struct vlist_tree *tree, struct vlist_node *node_new, ++ struct vlist_node *node_old) ++{ ++ struct bonding_member *bm; ++ struct device *dev; ++ ++ if (node_new) { ++ bm = container_of(node_new, struct bonding_member, node); ++ ++ if (node_old) { ++ free(bm); ++ return; ++ } ++ ++ dev = bm->dev.dev; ++ bm->dev.dev = NULL; ++ device_add_user(&bm->dev, dev); ++ } ++ ++ ++ if (node_old) { ++ bm = container_of(node_old, struct bonding_member, node); ++ bonding_free_member(bm); ++ } ++} ++ ++ ++static void ++bonding_add_member(struct bonding_state *bst, const char *name) ++{ ++ struct device *dev; ++ ++ dev = device_get(name, true); ++ if (!dev) ++ return; ++ ++ bonding_create_member(bst, dev, false); ++} ++ ++static int ++bonding_hotplug_add(struct device *dev, struct device *member) ++{ ++ struct bonding_state *bst = container_of(dev, struct bonding_state, dev); ++ ++ bonding_create_member(bst, member, true); ++ ++ return 0; ++} ++ ++static int ++bonding_hotplug_del(struct device *dev, struct device *member) ++{ ++ struct bonding_state *bst = container_of(dev, struct bonding_state, dev); ++ struct bonding_member *bm; ++ ++ bm = vlist_find(&bst->members, member->ifname, bm, node); ++ if (!bm) ++ return UBUS_STATUS_NOT_FOUND; ++ ++ vlist_delete(&bst->members, &bm->node); ++ return 0; ++} ++ ++static int ++bonding_hotplug_prepare(struct device *dev) ++{ ++ struct bonding_state *bst; ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ bst->force_active = true; ++ device_set_present(&bst->dev, true); ++ ++ return 0; ++} ++ ++static const struct device_hotplug_ops bonding_ops = { ++ .prepare = bonding_hotplug_prepare, ++ .add = bonding_hotplug_add, ++ .del = bonding_hotplug_del ++}; ++ ++static void ++bonding_free(struct device *dev) ++{ ++ struct bonding_state *bst; ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ vlist_flush_all(&bst->members); ++ free(bst); ++} ++ ++static void ++bonding_dump_info(struct device *dev, struct blob_buf *b) ++{ ++ struct bonding_state *bst; ++ struct bonding_member *bm; ++ void *list; ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ ++ system_if_dump_info(dev, b); ++ list = blobmsg_open_array(b, "bonding-members"); ++ ++ vlist_for_each_element(&bst->members, bm, node) ++ blobmsg_add_string(b, NULL, bm->dev.dev->ifname); ++ ++ blobmsg_close_array(b, list); ++} ++ ++static void ++bonding_config_init(struct device *dev) ++{ ++ struct bonding_state *bst; ++ struct blob_attr *cur; ++ int rem; ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ ++ if (!bst->ifnames) ++ return; ++ ++ vlist_update(&bst->members); ++ blobmsg_for_each_attr(cur, bst->ifnames, rem) { ++ bonding_add_member(bst, blobmsg_data(cur)); ++ } ++ vlist_flush(&bst->members); ++} ++ ++static void ++bonding_apply_settings(struct bonding_state *bst, struct blob_attr **tb) ++{ ++ struct bonding_config *cfg = &bst->config; ++ struct blob_attr *cur; ++ ++ /* defaults */ ++ cfg->mode = 0; ++ ++ if ((cur = tb[BONDING_ATTR_MODE])) ++ cfg->mode = blobmsg_get_u32(cur); ++ ++ if ((cur = tb[BONDING_ATTR_XMITHASHPOL])) { ++ memcpy(&cfg->xmit_hash_policy, blobmsg_get_string(cur), ++ sizeof(cfg->xmit_hash_policy)); ++ } ++} ++ ++enum dev_change_type ++bonding_reload(struct device *dev, struct blob_attr *attr) ++{ ++ struct blob_attr *tb_dev[__DEV_ATTR_MAX]; ++ struct blob_attr *tb_br[__BONDING_ATTR_MAX]; ++ enum dev_change_type ret = DEV_CONFIG_APPLIED; ++ unsigned long diff; ++ struct bonding_state *bst; ++ ++ BUILD_BUG_ON(sizeof(diff) < __BONDING_ATTR_MAX / 8); ++ BUILD_BUG_ON(sizeof(diff) < __DEV_ATTR_MAX / 8); ++ ++ bst = container_of(dev, struct bonding_state, dev); ++ ++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, tb_dev, ++ blob_data(attr), blob_len(attr)); ++ blobmsg_parse(bonding_attrs, __BONDING_ATTR_MAX, tb_br, ++ blob_data(attr), blob_len(attr)); ++ ++ bst->ifnames = tb_br[BONDING_ATTR_SLAVES]; ++ device_init_settings(dev, tb_dev); ++ bonding_apply_settings(bst, tb_br); ++ ++ if (bst->config_data) { ++ struct blob_attr *otb_dev[__DEV_ATTR_MAX]; ++ struct blob_attr *otb_br[__BONDING_ATTR_MAX]; ++ ++ blobmsg_parse(device_attr_list.params, __DEV_ATTR_MAX, otb_dev, ++ blob_data(bst->config_data), blob_len(bst->config_data)); ++ ++ diff = 0; ++ uci_blob_diff(tb_dev, otb_dev, &device_attr_list, &diff); ++ if (diff) ++ ret = DEV_CONFIG_RESTART; ++ ++ blobmsg_parse(bonding_attrs, __BONDING_ATTR_MAX, otb_br, ++ blob_data(bst->config_data), blob_len(bst->config_data)); ++ ++ diff = 0; ++ uci_blob_diff(tb_br, otb_br, &bonding_attr_list, &diff); ++ if (diff & ~(1 << BONDING_ATTR_IFNAME)) ++ ret = DEV_CONFIG_RESTART; ++ ++ bonding_config_init(dev); ++ } ++ ++ bst->config_data = attr; ++ return ret; ++} ++ ++static struct device * ++bonding_create(const char *name, struct device_type *devtype, struct blob_attr *attr) ++{ ++ struct bonding_state *bst; ++ struct device *dev = NULL; ++ ++ bst = calloc(1, sizeof(*bst)); ++ if (!bst) ++ return NULL; ++ ++ dev = &bst->dev; ++ device_init(dev, &bonding_device_type, name); ++ dev->config_pending = true; ++ ++ bst->set_state = dev->set_state; ++ dev->set_state = bonding_set_state; ++ ++ dev->hotplug_ops = &bonding_ops; ++ ++ vlist_init(&bst->members, avl_strcmp, bonding_member_update); ++ bst->members.keep_old = true; ++ bonding_reload(dev, attr); ++ ++ return dev; ++} ++ ++static void __init bonding_device_type_init(void) ++{ ++ device_type_add(&bonding_device_type); ++} +diff -Nur a/CMakeLists.txt netifd-2019-08-05-5e02f944/CMakeLists.txt +--- a/CMakeLists.txt 2020-05-01 16:08:04.229808359 -0700 ++++ netifd-2019-08-05-5e02f944/CMakeLists.txt 2020-05-01 16:08:23.473707648 -0700 +@@ -19,7 +19,7 @@ + main.c utils.c system.c tunnel.c handler.c + interface.c interface-ip.c interface-event.c + iprule.c proto.c proto-static.c proto-shell.c +- config.c device.c bridge.c veth.c vlan.c alias.c ++ config.c device.c bridge.c bonding.c veth.c vlan.c alias.c + macvlan.c ubus.c vlandev.c wireless.c) + + +diff -Nur a/config.c netifd-2019-08-05-5e02f944/config.c +--- a/config.c 2020-05-01 16:08:04.229808359 -0700 ++++ netifd-2019-08-05-5e02f944/config.c 2020-05-01 16:08:23.473707648 -0700 +@@ -72,13 +72,32 @@ + return 0; + } + ++static int ++config_parse_bonding_interface(struct uci_section *s) ++{ ++ const char *name = uci_lookup_option_string(uci_ctx, s, "ifname"); ++ if(!name) ++ { ++ D(INTERFACE, "no ifname specificed for bonding interface"); ++ return -EINVAL; ++ } ++ ++ uci_to_blob(&b, s, bonding_device_type.config_params); ++ if (!device_create(name, &bonding_device_type, b.head)) { ++ D(INTERFACE, "Failed to create bonding for interface '%s'\n", s->e.name); ++ return -EINVAL; ++ } ++ ++ return 0; ++} ++ + static void + config_parse_interface(struct uci_section *s, bool alias) + { + struct interface *iface; + const char *type = NULL, *disabled; + struct blob_attr *config; +- bool bridge = false; ++ bool is_simple_device = true; + struct device_type *devtype = NULL; + + disabled = uci_lookup_option_string(uci_ctx, s, "disabled"); +@@ -97,7 +116,13 @@ + if (config_parse_bridge_interface(s, devtype)) + return; + +- bridge = true; ++ is_simple_device = false; ++ } ++ else if (type && !strcmp(type, "bonding")) { ++ if (config_parse_bonding_interface(s)) ++ return; ++ ++ is_simple_device = false; + } + + uci_to_blob(&b, s, &interface_attr_list); +@@ -109,7 +134,7 @@ + if (iface->proto_handler && iface->proto_handler->config_params) + uci_to_blob(&b, s, iface->proto_handler->config_params); + +- if (!bridge && uci_to_blob(&b, s, simple_device_type.config_params)) ++ if (is_simple_device && uci_to_blob(&b, s, simple_device_type.config_params)) + iface->device_config = true; + + config = blob_memdup(b.head); +diff -Nur a/device.h netifd-2019-08-05-5e02f944/device.h +--- a/device.h 2020-05-01 16:08:04.229808359 -0700 ++++ netifd-2019-08-05-5e02f944/device.h 2020-05-01 16:08:23.473707648 -0700 +@@ -231,6 +231,7 @@ + extern const struct uci_blob_param_list device_attr_list; + extern struct device_type simple_device_type; + extern struct device_type tunnel_device_type; ++extern struct device_type bonding_device_type; + + void device_lock(void); + void device_unlock(void); +diff -Nur a/interface.c netifd-2019-08-05-5e02f944/interface.c +--- a/interface.c 2020-05-01 16:08:04.233808340 -0700 ++++ netifd-2019-08-05-5e02f944/interface.c 2020-05-01 16:08:23.473707648 -0700 +@@ -1241,6 +1241,7 @@ + + if_old->device_config = if_new->device_config; + if_old->config_autostart = if_new->config_autostart; ++ if_old->autostart = if_old->config_autostart; + if_old->ifname = if_new->ifname; + if_old->parent_ifname = if_new->parent_ifname; + if_old->dynamic = if_new->dynamic; +diff -Nur a/system-dummy.c netifd-2019-08-05-5e02f944/system-dummy.c +--- a/system-dummy.c 2020-05-01 16:08:04.233808340 -0700 ++++ netifd-2019-08-05-5e02f944/system-dummy.c 2020-05-01 16:08:23.473707648 -0700 +@@ -54,6 +54,30 @@ + return 0; + } + ++int system_bonding_addbonding(struct device *bonding, struct bridge_config *cfg) ++{ ++ D(SYSTEM, "bonding addbonding %s\n", bonding->ifname); ++ return 0; ++} ++ ++int system_bonding_delbonding(struct device *bonding) ++{ ++ D(SYSTEM, "bonding delbonding %s\n", bonding->ifname); ++ return 0; ++} ++ ++int system_bonding_addif(struct device *bonding, struct device *dev) ++{ ++ D(SYSTEM, "bonding addif %s %s\n", bonding->ifname, dev->ifname); ++ return 0; ++} ++ ++int system_bonding_delif(struct device *bonding, struct device *dev) ++{ ++ D(SYSTEM, "bonding delif %s %s\n", bonding->ifname, dev->ifname); ++ return 0; ++} ++ + int system_vlan_add(struct device *dev, int id) + { + D(SYSTEM, "vconfig add %s %d\n", dev->ifname, id); +diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h +--- a/system.h 2020-05-01 16:08:04.233808340 -0700 ++++ netifd-2019-08-05-5e02f944/system.h 2020-05-01 16:08:23.473707648 -0700 +@@ -128,6 +128,11 @@ + int hash_max; + }; + ++struct bonding_config { ++ int mode; ++ char xmit_hash_policy[16]; ++}; ++ + enum macvlan_opt { + MACVLAN_OPT_MACADDR = (1 << 0), + }; +@@ -186,6 +191,11 @@ + int system_bridge_addif(struct device *bridge, struct device *dev); + int system_bridge_delif(struct device *bridge, struct device *dev); + ++int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg); ++int system_bonding_delbonding(struct device *bonding); ++int system_bonding_addif(struct device *bonding, struct device *dev); ++int system_bonding_delif(struct device *bonding, struct device *dev); ++ + int system_macvlan_add(struct device *macvlan, struct device *dev, struct macvlan_config *cfg); + int system_macvlan_del(struct device *macvlan); + +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-05-01 16:08:04.233808340 -0700 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-01 16:08:23.477707628 -0700 +@@ -731,6 +731,15 @@ + return ioctl(sock_ioctl, SIOCBRDELBR, bridge->ifname); + } + ++int system_bonding_delbonding(struct device *bonding) ++{ ++ char cmd[32]; ++ snprintf(cmd, sizeof(cmd), "-%s", bonding->ifname); ++ system_set_sysctl("/sys/class/net/bonding_masters", cmd); ++ ++ return 0; ++} ++ + static int system_bridge_if(const char *bridge, struct device *dev, int cmd, void *data) + { + struct ifreq ifr; +@@ -744,6 +753,17 @@ + return ioctl(sock_ioctl, cmd, &ifr); + } + ++static bool system_is_bonding(const char *name, char *buf, int buflen) ++{ ++ struct stat st; ++ ++ snprintf(buf, buflen, "/sys/devices/virtual/net/%s/bonding", name); ++ if (stat(buf, &st) < 0) ++ return false; ++ ++ return true; ++} ++ + static bool system_is_bridge(const char *name, char *buf, int buflen) + { + struct stat st; +@@ -781,6 +801,34 @@ + return path + 1; + } + ++static struct device *system_get_bonding(const char *name, char *buf, int buflen) ++{ ++ char path[64], *devname; ++ int ifindex, len; ++ FILE *f; ++ ++ snprintf(path, sizeof(path), "/sys/class/net/%s/master/ifindex", name); ++ f = fopen(path, "r"); ++ if (!f) ++ return NULL; ++ ++ len = fread(buf, 1, buflen - 1, f); ++ fclose(f); ++ ++ if (len <= 0) ++ return NULL; ++ ++ buf[len] = 0; ++ ifindex = strtoul(buf, NULL, 0); ++ ++ devname = if_indextoname(ifindex, buf); ++ ++ if (!devname) ++ return NULL; ++ ++ return device_get(devname, false); ++} ++ + static void + system_bridge_set_wireless(struct device *bridge, struct device *dev) + { +@@ -835,6 +883,28 @@ + return ret; + } + ++int system_bonding_addif(struct device *bonding, struct device *dev) ++{ ++ char cmd[32]; ++ ++ system_if_down(dev); ++ snprintf(cmd, sizeof(cmd), "+%s", dev->ifname); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/slaves", bonding->ifname, cmd); ++ ++ return 0; ++} ++ ++int system_bonding_delif(struct device *bonding, struct device *dev) ++{ ++ char cmd[32]; ++ ++ snprintf(cmd, sizeof(cmd), "-%s", dev->ifname); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/slaves", bonding->ifname, cmd); ++ system_if_up(dev); ++ ++ return 0; ++} ++ + int system_bridge_delif(struct device *bridge, struct device *dev) + { + return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); +@@ -1040,11 +1110,19 @@ + { + static char buf[256]; + char *bridge; ++ struct device *bonding; ++ + device_set_ifindex(dev, system_if_resolve(dev)); + + if (dev->external || !dev->ifindex) + return; + ++ if (system_is_bonding(dev->ifname, buf, sizeof(buf))) { ++ D(SYSTEM, "Delete existing bonding named '%s'\n", dev->ifname); ++ system_bonding_delbonding(dev); ++ return; ++ } ++ + system_if_flags(dev->ifname, 0, IFF_UP); + + if (system_is_bridge(dev->ifname, buf, sizeof(buf))) { +@@ -1059,6 +1137,12 @@ + system_bridge_if(bridge, dev, SIOCBRDELIF, NULL); + } + ++ bonding = system_get_bonding(dev->ifname, buf, sizeof(buf)); ++ if (bonding) { ++ D(SYSTEM, "Remove device '%s' from bonding '%s'\n", dev->ifname, bonding->ifname); ++ system_bonding_delif(bonding, dev); ++ } ++ + system_if_clear_entries(dev, RTM_GETROUTE, AF_INET); + system_if_clear_entries(dev, RTM_GETADDR, AF_INET); + system_if_clear_entries(dev, RTM_GETROUTE, AF_INET6); +@@ -1068,6 +1152,23 @@ + system_set_disable_ipv6(dev, "0"); + } + ++int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg) ++{ ++ char cmd[32], mode[4], policy[16]; ++ ++ snprintf(cmd, sizeof(cmd), "+%s", bonding->ifname); ++ system_set_sysctl("/sys/class/net/bonding_masters", cmd); ++ ++ snprintf(mode, sizeof(mode), "%d", cfg->mode); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/mode", bonding->ifname, mode); ++ ++ snprintf(policy, sizeof(policy), "%s", cfg->xmit_hash_policy); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/xmit_hash_policy", ++ bonding->ifname, policy); ++ ++ return 0; ++} ++ + static inline unsigned long + sec_to_jiffies(int val) + { diff --git a/netifd/patches/011-add-sae-encryption.patch b/netifd/patches/011-add-sae-encryption.patch new file mode 100644 index 000000000..5af0fef38 --- /dev/null +++ b/netifd/patches/011-add-sae-encryption.patch @@ -0,0 +1,12 @@ +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -267,6 +267,9 @@ wireless_vif_parse_encryption() { + ;; + esac + ;; ++ *sae*) ++ auth_type=sae ++ ;; + esac + } + diff --git a/netifd/patches/011-support-bridge-hairpin.patch b/netifd/patches/011-support-bridge-hairpin.patch new file mode 100644 index 000000000..421da6207 --- /dev/null +++ b/netifd/patches/011-support-bridge-hairpin.patch @@ -0,0 +1,82 @@ +diff -Nur a/bridge.c netifd-2019-08-05-5e02f944/bridge.c +--- a/bridge.c 2020-05-01 16:39:45.875448393 -0700 ++++ netifd-2019-08-05-5e02f944/bridge.c 2020-05-01 16:43:05.086378758 -0700 +@@ -34,6 +34,7 @@ + BRIDGE_ATTR_BRIDGE_EMPTY, + BRIDGE_ATTR_MULTICAST_QUERIER, + BRIDGE_ATTR_HASH_MAX, ++ BRIDGE_ATTR_HAIRPIN, + BRIDGE_ATTR_ROBUSTNESS, + BRIDGE_ATTR_QUERY_INTERVAL, + BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL, +@@ -53,6 +54,7 @@ + [BRIDGE_ATTR_BRIDGE_EMPTY] = { "bridge_empty", BLOBMSG_TYPE_BOOL }, + [BRIDGE_ATTR_MULTICAST_QUERIER] = { "multicast_querier", BLOBMSG_TYPE_BOOL }, + [BRIDGE_ATTR_HASH_MAX] = { "hash_max", BLOBMSG_TYPE_INT32 }, ++ [BRIDGE_ATTR_HAIRPIN] = { "hairpin", BLOBMSG_TYPE_BOOL }, + [BRIDGE_ATTR_ROBUSTNESS] = { "robustness", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_QUERY_INTERVAL] = { "query_interval", BLOBMSG_TYPE_INT32 }, + [BRIDGE_ATTR_QUERY_RESPONSE_INTERVAL] = { "query_response_interval", BLOBMSG_TYPE_INT32 }, +@@ -219,6 +221,7 @@ + } + + device_set_present(&bst->dev, true); ++ system_bridge_set_hairpin(bm->dev.dev, bst->config.hairpin); + device_broadcast_event(&bst->dev, DEV_EVENT_TOPO_CHANGE); + + return 0; +@@ -577,6 +580,7 @@ + cfg->hash_max = 512; + cfg->bridge_empty = false; + cfg->priority = 0x7FFF; ++ cfg->hairpin = false; + + if ((cur = tb[BRIDGE_ATTR_STP])) + cfg->stp = blobmsg_get_bool(cur); +@@ -633,6 +637,10 @@ + + if ((cur = tb[BRIDGE_ATTR_BRIDGE_EMPTY])) + cfg->bridge_empty = blobmsg_get_bool(cur); ++ ++ if ((cur = tb[BRIDGE_ATTR_HAIRPIN])) ++ cfg->hairpin = blobmsg_get_bool(cur); ++ + } + + static enum dev_change_type +diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h +--- a/system.h 2020-05-01 16:39:45.879448372 -0700 ++++ netifd-2019-08-05-5e02f944/system.h 2020-05-01 16:40:35.427182113 -0700 +@@ -126,6 +126,7 @@ + int hello_time; + int max_age; + int hash_max; ++ int hairpin; + }; + + struct bonding_config { +@@ -190,6 +191,7 @@ + int system_bridge_delbr(struct device *bridge); + int system_bridge_addif(struct device *bridge, struct device *dev); + int system_bridge_delif(struct device *bridge, struct device *dev); ++void system_bridge_set_hairpin(struct device *dev, int enable); + + int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg); + int system_bonding_delbonding(struct device *bonding); +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-05-01 16:39:45.879448372 -0700 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-01 16:40:35.423182135 -0700 +@@ -910,6 +910,13 @@ + return system_bridge_if(bridge->ifname, dev, SIOCBRDELIF, NULL); + } + ++void system_bridge_set_hairpin(struct device *dev, int enable) ++{ ++ char mode[4]; ++ snprintf(mode, sizeof(mode), "%d", !!enable); ++ system_set_dev_sysctl("/sys/class/net/%s/brport/hairpin_mode", dev->ifname, mode); ++} ++ + int system_if_resolve(struct device *dev) + { + struct ifreq ifr; diff --git a/netifd/patches/015-linux-system-Set-MTU-while-adding-interfaces-to-brid.patch b/netifd/patches/015-linux-system-Set-MTU-while-adding-interfaces-to-brid.patch new file mode 100644 index 000000000..347d8b78b --- /dev/null +++ b/netifd/patches/015-linux-system-Set-MTU-while-adding-interfaces-to-brid.patch @@ -0,0 +1,109 @@ +diff -Nur a/system-dummy.c netifd-2019-08-05-5e02f944/system-dummy.c +--- a/system-dummy.c 2020-05-01 17:03:24.807952410 -0700 ++++ netifd-2019-08-05-5e02f944/system-dummy.c 2020-05-01 17:03:52.615805779 -0700 +@@ -310,6 +310,11 @@ + return 0; + } + ++int system_update_ipv4_mtu(struct device *dev, int mtu) ++{ ++ return 0; ++} ++ + int system_update_ipv6_mtu(struct device *dev, int mtu) + { + return 0; +diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h +--- a/system.h 2020-05-01 17:03:24.807952410 -0700 ++++ netifd-2019-08-05-5e02f944/system.h 2020-05-01 17:07:07.894774469 -0700 +@@ -253,6 +253,8 @@ + + void system_fd_set_cloexec(int fd); + ++int system_update_ipv4_mtu(struct device *device, int mtu); ++ + int system_update_ipv6_mtu(struct device *dev, int mtu); + + #endif +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-05-01 17:03:24.807952410 -0700 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-01 17:06:12.795065718 -0700 +@@ -852,6 +852,12 @@ + char *oldbr; + int ret = 0; + ++ if (bridge->settings.flags & DEV_OPT_MTU) { ++ system_update_ipv4_mtu(dev, bridge->settings.mtu); ++ } ++ if (bridge->settings.flags & DEV_OPT_MTU6) { ++ system_update_ipv6_mtu(dev, bridge->settings.mtu6); ++ } + oldbr = system_get_bridge(dev->ifname, dev_buf, sizeof(dev_buf)); + if (!oldbr || strcmp(oldbr, bridge->ifname) != 0) + ret = system_bridge_if(bridge->ifname, dev, SIOCBRADDIF, NULL); +@@ -1526,10 +1532,9 @@ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1); + +- if (ioctl(sock_ioctl, SIOCGIFMTU, &ifr) == 0) { +- s->mtu = ifr.ifr_mtu; ++ s->mtu = system_update_ipv4_mtu(dev, 0); ++ if (s->mtu > 0) + s->flags |= DEV_OPT_MTU; +- } + + s->mtu6 = system_update_ipv6_mtu(dev, 0); + if (s->mtu6 > 0) +@@ -1623,8 +1628,7 @@ + memset(&ifr, 0, sizeof(ifr)); + strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name) - 1); + if (s->flags & DEV_OPT_MTU & apply_mask) { +- ifr.ifr_mtu = s->mtu; +- if (ioctl(sock_ioctl, SIOCSIFMTU, &ifr) < 0) ++ if (system_update_ipv4_mtu(dev, s->mtu) < 0) + s->flags &= ~DEV_OPT_MTU; + } + if (s->flags & DEV_OPT_MTU6 & apply_mask) { +@@ -3360,12 +3364,42 @@ + return __system_del_ip_tunnel(name, tb); + } + ++int system_update_ipv4_mtu(struct device *dev, int mtu) ++{ ++ int ret = -1; ++ struct ifreq ifr; ++ ++ if(!dev) ++ return ret; ++ ++ memset(&ifr, 0, sizeof(ifr)); ++ ifr.ifr_addr.sa_family = AF_INET; ++ strncpy(ifr.ifr_name, dev->ifname, sizeof(ifr.ifr_name)); ++ ++ if (!mtu) { ++ ret = ioctl(sock_ioctl, SIOCGIFMTU, &ifr); ++ if (ret == 0) ++ ret = ifr.ifr_mtu; ++ } else { ++ struct device * parent = system_if_get_parent(dev); ++ if (parent) ++ system_update_ipv4_mtu(parent, mtu); ++ ++ ifr.ifr_mtu = mtu; ++ ret = ioctl(sock_ioctl, SIOCSIFMTU, &ifr); ++ } ++ return (ret == 0)?mtu:ret; ++} ++ + int system_update_ipv6_mtu(struct device *dev, int mtu) + { + int ret = -1; + char buf[64]; + int fd; + ++ if(!dev) ++ return ret; ++ + snprintf(buf, sizeof(buf), "/proc/sys/net/ipv6/conf/%s/mtu", + dev->ifname); + diff --git a/netifd/patches/050-ipv4-address-validation.patch b/netifd/patches/050-ipv4-address-validation.patch new file mode 100644 index 000000000..ff5cb89de --- /dev/null +++ b/netifd/patches/050-ipv4-address-validation.patch @@ -0,0 +1,35 @@ +diff -Nur a/utils.c netifd-2019-08-05-5e02f944/utils.c +--- a/utils.c 2020-06-04 11:54:37.287682451 -0700 ++++ netifd-2019-08-05-5e02f944/utils.c 2020-06-04 11:58:41.782809397 -0700 +@@ -118,9 +118,11 @@ + int + parse_ip_and_netmask(int af, const char *str, void *addr, unsigned int *netmask) + { +- char *astr = alloca(strlen(str) + 1); ++ int len = strlen(str) + 1; ++ char *astr = alloca(len); ++ int ret = 0; + +- strcpy(astr, str); ++ strncpy(astr, str, len); + if (!split_netmask(astr, netmask, af == AF_INET6)) + return 0; + +@@ -132,7 +134,16 @@ + return 0; + } + +- return inet_pton(af, astr, addr); ++ ret = inet_pton(af, astr, addr); ++ if ((ret > 0) && (af == AF_INET)) { ++ struct in_addr *ip4_addr = (struct in_addr *)addr; ++ uint32_t host_addr = ntohl(ip4_addr->s_addr); ++ ++ if (!IN_CLASSA(host_addr) && !IN_CLASSB(host_addr) && !IN_CLASSC(host_addr)) { ++ ret = 0; ++ } ++ } ++ return ret; + } + + char * diff --git a/netifd/patches/051-remove-fail_policy-rule.patch b/netifd/patches/051-remove-fail_policy-rule.patch new file mode 100644 index 000000000..c77ede914 --- /dev/null +++ b/netifd/patches/051-remove-fail_policy-rule.patch @@ -0,0 +1,12 @@ +diff -Nur a/interface-ip.c netifd-2019-08-05-5e02f944/interface-ip.c +--- a/interface-ip.c 2020-05-03 17:18:38.009128593 -0700 ++++ netifd-2019-08-05-5e02f944/interface-ip.c 2020-05-03 17:20:22.664628733 -0700 +@@ -1612,8 +1612,6 @@ + set_ip_lo_policy(enabled, true, ip->iface); + set_ip_lo_policy(enabled, false, ip->iface); + +- set_ip_source_policy(enabled, true, IPRULE_PRIORITY_REJECT + ip->iface->l3_dev.dev->ifindex, +- NULL, 0, 0, ip->iface, "failed_policy", true); + ip->iface->policy_rules_set = enabled; + } + } diff --git a/netifd/patches/052-add-support-to-avoid-ap-isolate.patch b/netifd/patches/052-add-support-to-avoid-ap-isolate.patch new file mode 100644 index 000000000..94ed9f0fc --- /dev/null +++ b/netifd/patches/052-add-support-to-avoid-ap-isolate.patch @@ -0,0 +1,11 @@ +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -280,7 +280,7 @@ _wireless_set_brsnoop_isolation() { + json_get_var isolate isolate + + [ ${isolate:-0} -gt 0 -o -z "$network_bridge" ] && return +- [ ${multicast_to_unicast:-1} -gt 0 ] && json_add_boolean isolate 1 ++ [ ${multicast_to_unicast:-0} -gt 0 ] && json_add_boolean isolate 1 + } + + for_each_interface() { diff --git a/netifd/patches/061-allow-setting-device-presence-for-wifi-interfaces.patch b/netifd/patches/061-allow-setting-device-presence-for-wifi-interfaces.patch new file mode 100644 index 000000000..1204122fa --- /dev/null +++ b/netifd/patches/061-allow-setting-device-presence-for-wifi-interfaces.patch @@ -0,0 +1,12 @@ +--- netifd-2015-12-16.orig/device.c ++++ netifd-2015-12-16/device.c +@@ -424,9 +424,6 @@ + { + struct device *dev; + +- if (!external && system_if_force_external(name)) +- return NULL; +- + D(DEVICE, "Create simple device '%s'\n", name); + dev = calloc(1, sizeof(*dev)); + dev->external = external; diff --git a/netifd/patches/080-add-L2DA-option-to-use-slaves-own-MAC-addresses.patch b/netifd/patches/080-add-L2DA-option-to-use-slaves-own-MAC-addresses.patch new file mode 100644 index 000000000..b6bde4b3b --- /dev/null +++ b/netifd/patches/080-add-L2DA-option-to-use-slaves-own-MAC-addresses.patch @@ -0,0 +1,67 @@ +--- netifd-2015-12-16.orig/bonding.c ++++ netifd-2015-12-16/bonding.c +@@ -28,6 +28,7 @@ + BONDING_ATTR_SLAVES, + BONDING_ATTR_MODE, + BONDING_ATTR_XMITHASHPOL, ++ BONDING_ATTR_L2DA_MULTIMAC, + __BONDING_ATTR_MAX + }; + +@@ -36,6 +37,7 @@ + [BONDING_ATTR_SLAVES] = { "slaves", BLOBMSG_TYPE_ARRAY }, + [BONDING_ATTR_MODE] = { "mode", BLOBMSG_TYPE_INT32 }, + [BONDING_ATTR_XMITHASHPOL] = { "xmit_hash_policy", BLOBMSG_TYPE_STRING }, ++ [BONDING_ATTR_L2DA_MULTIMAC] = { "l2da_multimac", BLOBMSG_TYPE_INT32 }, + }; + + static const struct uci_blob_param_info bonding_attr_info[__BONDING_ATTR_MAX] = { +@@ -455,6 +457,7 @@ + + /* defaults */ + cfg->mode = 0; ++ cfg->l2da_multimac = 0; + + if ((cur = tb[BONDING_ATTR_MODE])) + cfg->mode = blobmsg_get_u32(cur); +@@ -463,6 +466,9 @@ + memcpy(&cfg->xmit_hash_policy, blobmsg_get_string(cur), + sizeof(cfg->xmit_hash_policy)); + } ++ ++ if ((cur = tb[BONDING_ATTR_L2DA_MULTIMAC])) ++ cfg->l2da_multimac = blobmsg_get_u32(cur); + } + + enum dev_change_type +--- netifd-2015-12-16.orig/system-linux.c ++++ netifd-2015-12-16/system-linux.c +@@ -924,7 +924,7 @@ + + int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg) + { +- char cmd[32], mode[4], policy[16]; ++ char cmd[32], mode[4], l2da_multimac[4], policy[16]; + + snprintf(cmd, sizeof(cmd), "+%s", bonding->ifname); + system_set_sysctl("/sys/class/net/bonding_masters", cmd); +@@ -932,6 +932,9 @@ + snprintf(mode, sizeof(mode), "%d", cfg->mode); + system_set_dev_sysctl("/sys/class/net/%s/bonding/mode", bonding->ifname, mode); + ++ snprintf(l2da_multimac, sizeof(l2da_multimac), "%d", cfg->l2da_multimac); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/l2da_multimac", bonding->ifname, l2da_multimac); ++ + snprintf(policy, sizeof(policy), "%s", cfg->xmit_hash_policy); + system_set_dev_sysctl("/sys/class/net/%s/bonding/xmit_hash_policy", + bonding->ifname, policy); +--- netifd-2015-12-16.orig/system.h ++++ netifd-2015-12-16/system.h +@@ -64,6 +64,7 @@ + + struct bonding_config { + int mode; ++ int l2da_multimac; + char xmit_hash_policy[16]; + }; + diff --git a/netifd/patches/081-do-not-fetch-device-settings.patch b/netifd/patches/081-do-not-fetch-device-settings.patch new file mode 100644 index 000000000..26ddda909 --- /dev/null +++ b/netifd/patches/081-do-not-fetch-device-settings.patch @@ -0,0 +1,10 @@ +--- a/device.c ++++ b/device.c +@@ -338,7 +338,6 @@ int device_claim(struct device_user *dep + if (!dev->ifindex) + ret = -1; + +- system_if_get_settings(dev, &dev->orig_settings); + } else + ret = dev->set_state(dev, true); + diff --git a/netifd/patches/082-apply-vlan-mtu-to-real-when-larger.patch b/netifd/patches/082-apply-vlan-mtu-to-real-when-larger.patch new file mode 100644 index 000000000..e8bddc747 --- /dev/null +++ b/netifd/patches/082-apply-vlan-mtu-to-real-when-larger.patch @@ -0,0 +1,82 @@ +diff -Nur a/system-dummy.c netifd-2019-08-05-5e02f944/system-dummy.c +--- a/system-dummy.c 2020-05-04 10:18:55.245933547 -0700 ++++ netifd-2019-08-05-5e02f944/system-dummy.c 2020-05-04 10:19:21.505807825 -0700 +@@ -130,6 +130,12 @@ + } + + struct device * ++system_if_apply_vlan_real(struct device *dev, int mtu) ++{ ++ return NULL; ++} ++ ++struct device * + system_if_get_parent(struct device *dev) + { + return NULL; +diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h +--- a/system.h 2020-05-04 10:18:55.245933547 -0700 ++++ netifd-2019-08-05-5e02f944/system.h 2020-05-04 10:19:21.509807807 -0700 +@@ -221,6 +221,7 @@ + int system_if_dump_info(struct device *dev, struct blob_buf *b); + int system_if_dump_stats(struct device *dev, struct blob_buf *b); + struct device *system_if_get_parent(struct device *dev); ++struct device *system_if_apply_vlan_real(struct device *dev, int mtu); + bool system_if_force_external(const char *ifname); + void system_if_apply_settings(struct device *dev, struct device_settings *s, + unsigned int apply_mask); +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-05-04 10:18:55.245933547 -0700 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-04 10:19:33.277751264 -0700 +@@ -1834,6 +1834,39 @@ + return device_get(devname, true); + } + ++struct device * ++system_if_apply_vlan_real(struct device *dev, int mtu) ++{ ++ char buf[64]; ++ int len, pmtu; ++ struct device *parentdev; ++ FILE *f; ++ ++ /* Check if it is a vlan device. */ ++ snprintf(buf, sizeof(buf), "/proc/net/vlan/%s", dev->ifname); ++ if (access(buf, F_OK) == -1) ++ return NULL; ++ ++ /* Get the vlan real device. */ ++ parentdev = system_if_get_parent(dev); ++ ++ /* Check if real device's mtu is less than new mtu. */ ++ snprintf(buf, sizeof(buf), "/sys/class/net/%s/mtu", parentdev->ifname); ++ f = fopen(buf, "r"); ++ if (!f) ++ return NULL; ++ ++ len = fread(buf, 1, sizeof(buf) - 1, f); ++ fclose(f); ++ ++ buf[len] = 0; ++ pmtu= strtoul(buf, NULL, 0); ++ if (!pmtu || pmtu >= (mtu + 4)) ++ return NULL; ++ ++ return parentdev; ++} ++ + static bool + read_string_file(int dir_fd, const char *file, char *buf, int len) + { +@@ -3384,9 +3417,9 @@ + if (ret == 0) + ret = ifr.ifr_mtu; + } else { +- struct device * parent = system_if_get_parent(dev); ++ struct device * parent = system_if_apply_vlan_real(dev, mtu); + if (parent) +- system_update_ipv4_mtu(parent, mtu); ++ system_update_ipv4_mtu(parent, mtu + 4); + + ifr.ifr_mtu = mtu; + ret = ioctl(sock_ioctl, SIOCSIFMTU, &ifr); diff --git a/netifd/patches/083-tunipip6-support-draft03.patch b/netifd/patches/083-tunipip6-support-draft03.patch new file mode 100644 index 000000000..7109bc889 --- /dev/null +++ b/netifd/patches/083-tunipip6-support-draft03.patch @@ -0,0 +1,59 @@ +Author: Ken Zhu +Date: Mon Mar 12 11:23:11 2018 -0700 + + netifd: add rfc7597 draft03 version support for tunipip6 + + draft03 version of rfc7597 has a little different from + the standard version. + + Change-Id: Ide3692ffd763c1741c96134b5df42446045f85bf + Signed-off-by: Ken Zhu + +diff -Nur a/system.c netifd-2019-08-05-5e02f944/system.c +--- a/system.c 2020-11-11 17:40:14.360936791 -0800 ++++ netifd-2019-08-05-5e02f944/system.c 2020-11-11 17:40:28.996873250 -0800 +@@ -89,9 +89,10 @@ + .params = sixrd_data_attrs, + }; + +-static const struct blobmsg_policy ipip6_data_attrs[__SIXRD_DATA_ATTR_MAX] = { ++static const struct blobmsg_policy ipip6_data_attrs[__IPIP6_DATA_ATTR_MAX] = { + [IPIP6_DATA_ENCAPLIMIT] = { .name = "encaplimit", .type = BLOBMSG_TYPE_STRING }, + [IPIP6_DATA_FMRS] = { .name = "fmrs", .type = BLOBMSG_TYPE_ARRAY }, ++ [IPIP6_DATA_DRAFT03] = { .name = "draft03", .type = BLOBMSG_TYPE_INT32 }, + }; + + const struct uci_blob_param_list ipip6_data_attr_list = { +diff -Nur a/system.h netifd-2019-08-05-5e02f944/system.h +--- a/system.h 2020-11-11 17:40:14.364936773 -0800 ++++ netifd-2019-08-05-5e02f944/system.h 2020-11-11 17:40:28.996873250 -0800 +@@ -77,6 +77,7 @@ + enum ipip6_data { + IPIP6_DATA_ENCAPLIMIT, + IPIP6_DATA_FMRS, ++ IPIP6_DATA_DRAFT03, + __IPIP6_DATA_ATTR_MAX + }; + +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-11-11 17:40:14.360936791 -0800 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-11-11 17:45:05.427539372 -0800 +@@ -2673,6 +2673,18 @@ + } + } + ++#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) ++ unsigned int draft03 = 0; ++ if ((cur = tb[IPIP6_DATA_DRAFT03])) { ++ draft03 = blobmsg_get_u32(cur); ++ if (ttl > 255) ++ return -EINVAL; ++ if (draft03) ++ nla_put_u8(nlm, IFLA_IPTUN_DRAFT03, 1); ++ } ++ ++#endif ++ + #ifdef IFLA_IPTUN_FMR_MAX + if ((cur = tb_data[IPIP6_DATA_FMRS])) { + struct blob_attr *rcur; diff --git a/netifd/patches/084-enlarge-nlmsg-size.patch b/netifd/patches/084-enlarge-nlmsg-size.patch new file mode 100644 index 000000000..e351c6ecd --- /dev/null +++ b/netifd/patches/084-enlarge-nlmsg-size.patch @@ -0,0 +1,26 @@ +diff -Nur a/system-linux.c netifd-2019-08-05-5e02f944/system-linux.c +--- a/system-linux.c 2020-05-04 12:50:37.870719671 -0700 ++++ netifd-2019-08-05-5e02f944/system-linux.c 2020-05-04 12:57:00.512680452 -0700 +@@ -2561,8 +2561,7 @@ + static int system_add_ip6_tunnel(const char *name, const unsigned int link, + struct blob_attr **tb) + { +- struct nl_msg *nlm = nlmsg_alloc_simple(RTM_NEWLINK, +- NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE); ++ struct nl_msg *nlm = nlmsg_alloc_size(65536); + struct ifinfomsg ifi = { .ifi_family = AF_UNSPEC }; + struct blob_attr *cur; + int ret = 0, ttl = 0; +@@ -2570,6 +2569,12 @@ + if (!nlm) + return -1; + ++ struct nlmsghdr *new = nlm->nm_nlh; ++ new->nlmsg_type = RTM_NEWLINK; ++ new->nlmsg_flags = NLM_F_REQUEST | NLM_F_REPLACE | NLM_F_CREATE; ++ new->nlmsg_seq = 0; ++ new->nlmsg_pid = 0; ++ + nlmsg_append(nlm, &ifi, sizeof(ifi), 0); + nla_put_string(nlm, IFLA_IFNAME, name); + diff --git a/netifd/patches/085-get-ifindex-in-file-if-ioctl-fail.patch b/netifd/patches/085-get-ifindex-in-file-if-ioctl-fail.patch new file mode 100644 index 000000000..3c11ecfb0 --- /dev/null +++ b/netifd/patches/085-get-ifindex-in-file-if-ioctl-fail.patch @@ -0,0 +1,46 @@ +diff -Nur a/system-linux.c netifd-2015-12-16/system-linux.c +--- a/system-linux.c 2018-11-08 15:30:16.422606326 -0800 ++++ netifd-2015-12-16/system-linux.c 2018-11-08 15:30:24.522606530 -0800 +@@ -593,6 +593,33 @@ + return path + 1; + } + ++static int system_get_ifindex(const char *name) ++{ ++ char path[64], buf[24]; ++ int len; ++ FILE *f; ++ struct stat st; ++ ++ snprintf(path, sizeof(path), "/sys/class/net/%s/ifindex", name); ++ ++ if (stat(path, &st) < 0) ++ return 0; ++ ++ f = fopen(path, "r"); ++ if (!f) { ++ return 0; ++ } ++ ++ len = fread(buf, 1, 23, f); ++ fclose(f); ++ ++ if (len <= 0) ++ return 0; ++ ++ buf[len] = 0; ++ return strtoul(buf, NULL, 0); ++} ++ + static struct device *system_get_bonding(const char *name, char *buf, int buflen) + { + char path[64], *devname; +@@ -706,7 +733,7 @@ + if (!ioctl(sock_ioctl, SIOCGIFINDEX, &ifr)) + return ifr.ifr_ifindex; + else +- return 0; ++ return system_get_ifindex(dev->ifname); + } + + static int system_if_flags(const char *ifname, unsigned add, unsigned rem) diff --git a/netifd/patches/086-allow-setting-device-presence-for-wifi-devices.patch b/netifd/patches/086-allow-setting-device-presence-for-wifi-devices.patch new file mode 100644 index 000000000..923151899 --- /dev/null +++ b/netifd/patches/086-allow-setting-device-presence-for-wifi-devices.patch @@ -0,0 +1,13 @@ +diff -Nur a/system-linux.c netifd-2015-12-16/system-linux.c +--- a/system-linux.c 2019-03-21 17:40:26.293950378 -0700 ++++ netifd-2015-12-16/system-linux.c 2019-03-21 17:40:43.161949878 -0700 +@@ -483,9 +483,6 @@ + if (dev->type != &simple_device_type) + return; + +- if (add && system_if_force_external(dev->ifname)) +- return; +- + device_set_present(dev, add); + } + diff --git a/netifd/patches/087-add-second-center-frequence-for-VHT80+80.patch b/netifd/patches/087-add-second-center-frequence-for-VHT80+80.patch new file mode 100644 index 000000000..a1a80d2f6 --- /dev/null +++ b/netifd/patches/087-add-second-center-frequence-for-VHT80+80.patch @@ -0,0 +1,21 @@ +diff -Nur a/scripts/netifd-wireless.sh netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh +--- a/scripts/netifd-wireless.sh 2020-05-04 13:21:10.706128891 -0700 ++++ netifd-2019-08-05-5e02f944/scripts/netifd-wireless.sh 2020-05-04 13:23:52.321399854 -0700 +@@ -39,7 +39,7 @@ + } + + _wdev_prepare_channel() { +- json_get_vars channel hwmode ++ json_get_vars channel hwmode cfreq2 + + auto_channel=0 + enable_ht=0 +@@ -329,7 +329,7 @@ + } + + _wdev_common_device_config() { +- config_add_string channel hwmode htmode noscan ++ config_add_string channel hwmode htmode noscan cfreq2 + } + + _wdev_common_iface_config() { diff --git a/netifd/patches/088-add-lacp_rate_enable-option.patch b/netifd/patches/088-add-lacp_rate_enable-option.patch new file mode 100644 index 000000000..32950cf6c --- /dev/null +++ b/netifd/patches/088-add-lacp_rate_enable-option.patch @@ -0,0 +1,71 @@ +diff -Nur a/bonding.c netifd-2015-12-16/bonding.c +--- a/bonding.c 2019-09-19 14:34:58.459599942 -0700 ++++ netifd-2015-12-16/bonding.c 2019-09-19 14:50:09.374322419 -0700 +@@ -29,6 +29,7 @@ + BONDING_ATTR_MODE, + BONDING_ATTR_XMITHASHPOL, + BONDING_ATTR_L2DA_MULTIMAC, ++ BONDING_ATTR_LACP_RATE_ENABLED, + __BONDING_ATTR_MAX + }; + +@@ -38,6 +39,7 @@ + [BONDING_ATTR_MODE] = { "mode", BLOBMSG_TYPE_INT32 }, + [BONDING_ATTR_XMITHASHPOL] = { "xmit_hash_policy", BLOBMSG_TYPE_STRING }, + [BONDING_ATTR_L2DA_MULTIMAC] = { "l2da_multimac", BLOBMSG_TYPE_INT32 }, ++ [BONDING_ATTR_LACP_RATE_ENABLED] = { "lacp_rate_enabled", BLOBMSG_TYPE_BOOL }, + }; + + static const struct uci_blob_param_info bonding_attr_info[__BONDING_ATTR_MAX] = { +@@ -458,6 +460,7 @@ + /* defaults */ + cfg->mode = 0; + cfg->l2da_multimac = 0; ++ cfg->lacp_rate_enabled = 0; + + if ((cur = tb[BONDING_ATTR_MODE])) + cfg->mode = blobmsg_get_u32(cur); +@@ -469,6 +472,10 @@ + + if ((cur = tb[BONDING_ATTR_L2DA_MULTIMAC])) + cfg->l2da_multimac = blobmsg_get_u32(cur); ++ ++ if ((cur = tb[BONDING_ATTR_LACP_RATE_ENABLED])) ++ cfg->lacp_rate_enabled = blobmsg_get_bool(cur); ++ + } + + enum dev_change_type +diff -Nur a/system.h netifd-2015-12-16/system.h +--- a/system.h 2019-09-19 14:34:58.459599942 -0700 ++++ netifd-2015-12-16/system.h 2019-09-19 14:42:52.014826386 -0700 +@@ -66,6 +66,7 @@ + struct bonding_config { + int mode; + int l2da_multimac; ++ bool lacp_rate_enabled; + char xmit_hash_policy[16]; + }; + +diff -Nur a/system-linux.c netifd-2015-12-16/system-linux.c +--- a/system-linux.c 2019-09-19 14:34:58.435600178 -0700 ++++ netifd-2015-12-16/system-linux.c 2019-09-19 14:47:45.839806369 -0700 +@@ -949,6 +949,7 @@ + int system_bonding_addbonding(struct device *bonding, struct bonding_config *cfg) + { + char cmd[32], mode[4], l2da_multimac[4], policy[16]; ++ char lacp_rate_enabled[4]; + + snprintf(cmd, sizeof(cmd), "+%s", bonding->ifname); + system_set_sysctl("/sys/class/net/bonding_masters", cmd); +@@ -963,6 +964,10 @@ + system_set_dev_sysctl("/sys/class/net/%s/bonding/xmit_hash_policy", + bonding->ifname, policy); + ++ snprintf(lacp_rate_enabled, sizeof(lacp_rate_enabled), "%d", cfg->lacp_rate_enabled); ++ system_set_dev_sysctl("/sys/class/net/%s/bonding/lacp_rate", ++ bonding->ifname, lacp_rate_enabled); ++ + return 0; + } + diff --git a/netifd/patches/089-authsae-add-support-to-parse-encypiton-tye-sae-and-s.patch b/netifd/patches/089-authsae-add-support-to-parse-encypiton-tye-sae-and-s.patch new file mode 100644 index 000000000..802c152e6 --- /dev/null +++ b/netifd/patches/089-authsae-add-support-to-parse-encypiton-tye-sae-and-s.patch @@ -0,0 +1,34 @@ +From a2bbbb0b4c13f060b21e5ea34839ec665963a635 Mon Sep 17 00:00:00 2001 +From: Venkateswara Naralasetty +Date: Thu, 19 Dec 2019 17:42:24 +0530 +Subject: [PATCH] authsae: add support to parse encypiton tye sae and sae-mixed + +this patch add support to parse encyption type sae and +sae-mixed mode. + +Signed-off-by: Venkateswara Naralasetty +--- + scripts/netifd-wireless.sh | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -201,7 +201,7 @@ wireless_vif_parse_encryption() { + + case "$encryption" in + *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";; +- *aes|*ccmp| psk2 | wpa2) wpa_cipher="CCMP";; ++ *aes|*ccmp| psk2 | wpa2 | sae*) wpa_cipher="CCMP";; + *tkip | wpa | psk ) wpa_cipher="TKIP";; + *gcmp) wpa_cipher="GCMP";; + esac +@@ -281,6 +281,9 @@ wireless_vif_parse_encryption() { + ;; + esac + ;; ++ sae-mixed) ++ auth_type=sae-mixed ++ ;; + *sae*) + auth_type=sae + ;; diff --git a/netifd/patches/090-add-support-for-owe.patch b/netifd/patches/090-add-support-for-owe.patch new file mode 100644 index 000000000..b89fb5eda --- /dev/null +++ b/netifd/patches/090-add-support-for-owe.patch @@ -0,0 +1,34 @@ +From 9cee2ce25a98adeedd230983dba2c9e12e456d01 Mon Sep 17 00:00:00 2001 +From: Aloka Dixit +Date: Wed, 16 Sep 2020 15:54:56 -0700 +Subject: [PATCH] auth: Add support for Opportunistic Wireless Encryption + +This patch adds support for OWE in wireless configuration file. +Use 'option encryption owe'. + +Signed-off-by: Aloka Dixit +--- + scripts/netifd-wireless.sh | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -201,7 +201,7 @@ wireless_vif_parse_encryption() { + + case "$encryption" in + *tkip+aes|*tkip+ccmp|*aes+tkip|*ccmp+tkip) wpa_cipher="CCMP TKIP";; +- *aes|*ccmp| psk2 | wpa2 | sae*) wpa_cipher="CCMP";; ++ *aes|*ccmp| psk2 | wpa2 | sae* | owe) wpa_cipher="CCMP";; + *tkip | wpa | psk ) wpa_cipher="TKIP";; + *gcmp) wpa_cipher="GCMP";; + esac +@@ -287,6 +287,9 @@ wireless_vif_parse_encryption() { + *sae*) + auth_type=sae + ;; ++ owe) ++ auth_type=owe ++ ;; + esac + } + diff --git a/netifd/patches/090-fix-link-up-event-cause-dep-interface-down.patch b/netifd/patches/090-fix-link-up-event-cause-dep-interface-down.patch new file mode 100644 index 000000000..46d428cc9 --- /dev/null +++ b/netifd/patches/090-fix-link-up-event-cause-dep-interface-down.patch @@ -0,0 +1,23 @@ +Author: Ken Zhu +Date: Fri Apr 9 08:35:20 2021 -0700 + + netifd: fix link up event causes interface down + + The interface down process should filter out link up + event besides interface up and update event. + + Change-Id: I4194ea0625a16d98f82dc7aaa699fbb2a8c21bdd + Signed-off-by: Ken Zhu + +diff -Nur a/proto-shell.c netifd-2021-01-09-753c351b/proto-shell.c +--- a/proto-shell.c 2021-04-08 17:50:06.008898194 -0700 ++++ netifd-2021-01-09-753c351b/proto-shell.c 2021-04-08 17:50:24.256630830 -0700 +@@ -269,7 +269,7 @@ + struct proto_shell_dependency *pdep; + struct proto_shell_state *state; + +- if (ev == IFEV_UP || ev == IFEV_UPDATE) ++ if (ev == IFEV_UP || ev == IFEV_UPDATE || ev == IFEV_LINK_UP) + return; + + pdep = container_of(dep, struct proto_shell_dependency, dep); diff --git a/netifd/patches/091-fix-ip-lost.patch b/netifd/patches/091-fix-ip-lost.patch new file mode 100644 index 000000000..e7b47e043 --- /dev/null +++ b/netifd/patches/091-fix-ip-lost.patch @@ -0,0 +1,50 @@ +Author: Ken Zhu +Date: Thu Dec 17 09:08:39 2020 -0800 + + netifd: fix ip lost after dhcp renew + + When two more IPv4 addresses of the same subnetwork are assigned + to one device, if the primary address got deleted, the rest IP + addresses could be deleted as well. + + To make sure that old IPv4 address deleted before assigning the + new address, both of them must be proceeded in one time. + + Change-Id: Ib989955c1511a14d34a5a45df1ad7e8713815b42 + Signed-off-by: Ken Zhu + +diff -Nur a/interface-ip.c netifd-2019-08-05-5e02f944/interface-ip.c +--- a/interface-ip.c 2021-01-26 13:08:43.624405844 -0800 ++++ netifd-2019-08-05-5e02f944/interface-ip.c 2021-01-26 13:11:14.935635800 -0800 +@@ -509,9 +509,23 @@ + free(route); + } + ++/* ++ * addr_cmp ++ * return 0 if two ipv6 addresses and its netmask are same ++ * return 0 if two ipv4 addresses are in the same subnetwork. ++ */ + static int + addr_cmp(const void *k1, const void *k2, void *ptr) + { ++ struct device_addr *addr1, *addr2; ++ addr1 = container_of(k1, struct device_addr, flags); ++ addr2 = container_of(k2, struct device_addr, flags); ++ if (((addr1->flags & DEVADDR_FAMILY) == DEVADDR_INET4) ++ && ((addr2->flags & DEVADDR_FAMILY) == DEVADDR_INET4)) { ++ return (ntohl(addr1->addr.in.s_addr) & (~((1 << (32 - addr1->mask)) - 1))) != ++ (ntohl(addr2->addr.in.s_addr) & (~((1 << (32 - addr2->mask)) - 1))); ++ } ++ + return memcmp(k1, k2, sizeof(struct device_addr) - + offsetof(struct device_addr, flags)); + } +@@ -662,6 +676,7 @@ + + if (((a_new->flags & DEVADDR_FAMILY) == DEVADDR_INET4) && + (a_new->broadcast != a_old->broadcast || ++ a_new->addr.in.s_addr != a_old->addr.in.s_addr || + a_new->point_to_point != a_old->point_to_point)) + keep = false; + } diff --git a/netifd/patches/092-fix-tb-data.patch b/netifd/patches/092-fix-tb-data.patch new file mode 100644 index 000000000..7478aaf47 --- /dev/null +++ b/netifd/patches/092-fix-tb-data.patch @@ -0,0 +1,12 @@ +diff -Nur netifd-copy/system-linux.c netifd-2021-01-09-753c351b/system-linux.c +--- netifd-copy/system-linux.c 2021-07-19 18:54:43.163143412 -0700 ++++ netifd-2021-01-09-753c351b/system-linux.c 2021-07-19 18:56:23.355608327 -0700 +@@ -2675,7 +2675,7 @@ + + #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,4,0) + unsigned int draft03 = 0; +- if ((cur = tb[IPIP6_DATA_DRAFT03])) { ++ if ((cur = tb_data[IPIP6_DATA_DRAFT03])) { + draft03 = blobmsg_get_u32(cur); + if (ttl > 255) + return -EINVAL; diff --git a/netifd/patches/093-fix-sae-and-sae-mixed-support.patch b/netifd/patches/093-fix-sae-and-sae-mixed-support.patch new file mode 100644 index 000000000..d6f083fcb --- /dev/null +++ b/netifd/patches/093-fix-sae-and-sae-mixed-support.patch @@ -0,0 +1,37 @@ +From a94c7d4917f54bb9929d9c247149eb0c400aac36 Mon Sep 17 00:00:00 2001 +From: Aditya Kumar Singh +Date: Wed, 10 Nov 2021 16:03:56 +0530 +Subject: [PATCH] fix sae and sae-mixed support + +sae and sae-mixed support due to commit id +22476ff99ea2c233e342dfe2bdff506e54278f03 in upstream +is conflicting the already existing sae and sae-mixed +support. + +This fixes this issue. + +Signed-off-by: Aditya Kumar Singh +--- + scripts/netifd-wireless.sh | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/scripts/netifd-wireless.sh b/scripts/netifd-wireless.sh +index 2dca493..b604e52 100644 +--- a/scripts/netifd-wireless.sh ++++ b/scripts/netifd-wireless.sh +@@ -249,10 +249,10 @@ wireless_vif_parse_encryption() { + wpa3*) + auth_type=eap192 + ;; +- psk3-mixed*|sae-mixed*) ++ psk3-mixed*) + auth_type=psk-sae + ;; +- psk3*|sae*) ++ psk3*) + auth_type=sae + ;; + *psk*) +-- +2.7.4 +