diff --git a/package/base-files/Makefile b/package/base-files/Makefile index 5487e1128..025b72a3b 100644 --- a/package/base-files/Makefile +++ b/package/base-files/Makefile @@ -39,7 +39,11 @@ endif define Package/base-files SECTION:=base CATEGORY:=Base system - DEPENDS:=+netifd +libc +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:openwrt-keyring +NAND_SUPPORT:ubi-utils +fstools +fwtool + DEPENDS:= \ + +netifd +libc +jsonfilter +SIGNED_PACKAGES:usign +SIGNED_PACKAGES:openwrt-keyring \ + +NAND_SUPPORT:ubi-utils +fstools +fwtool \ + +SELINUX:procd-selinux +!SELINUX:procd +USE_SECCOMP:procd-seccomp \ + +SELINUX:busybox-selinux +!SELINUX:busybox TITLE:=Base filesystem for LEDE URL:=http://openwrt.org/ VERSION:=$(PKG_RELEASE)-$(REVISION) @@ -108,6 +112,9 @@ define Build/Prepare mkdir -p $(PKG_BUILD_DIR) endef +define Build/Quilt +endef + define Build/Compile/Default endef @@ -135,7 +142,6 @@ ifndef CONFIG_BUILDBOT define Package/base-files/install-key mkdir -p $(1)/etc/opkg/keys $(CP) $(BUILD_KEY).pub $(1)/etc/opkg/keys/`$(STAGING_DIR_HOST)/bin/usign -F -p $(BUILD_KEY).pub` - endef endif endif @@ -147,17 +153,18 @@ ifeq ($(CONFIG_NAND_SUPPORT),) endef endif +ifeq ($(CONFIG_EMMC_SUPPORT),) + define Package/base-files/emmc-support + rm -f $(1)/lib/upgrade/emmc.sh + endef +endif + ifeq ($(CONFIG_LEGACY_SDCARD_SUPPORT),) define Package/base-files/legacy-sdcard-support rm -f $(1)/lib/upgrade/legacy-sdcard.sh endef endif -ifeq ($(CONFIG_EMMC_SUPPORT),) - define Package/base-files/emmc-support - rm -f $(1)/lib/upgrade/emmc.sh - endef -endif define Package/base-files/install $(CP) ./files/* $(1)/ @@ -204,7 +211,8 @@ define Package/base-files/install $(1)/usr/lib \ $(1)/usr/bin \ $(1)/sys \ - $(1)/www \ + $(1)/www + mkdir -p -m 750 \ $(1)/root $(LN) /proc/mounts $(1)/etc/mtab @@ -238,6 +246,13 @@ endif cat $(BIN_DIR)/feeds.buildinfo >>$(1)/etc/build.feeds; \ cat $(BIN_DIR)/version.buildinfo >>$(1)/etc/build.version) + $(if $(CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE), \ + rm -f $(1)/etc/banner.failsafe,) + + if [ ! -f $(TOPDIR)/feeds/luci/package.json ]; then \ + $(CP) ./luci/* $(1)/; \ + fi + ifneq ($(CONFIG_USE_APK),) mkdir -p $(1)/etc/apk/repositories.d $(call FeedSourcesAppendAPK,$(1)/etc/apk/repositories.d/distfeeds.list) @@ -254,13 +269,6 @@ else $(if $(CONFIG_IPK_FILES_CHECKSUMS),, \ rm -f $(1)/sbin/pkg_check) endif - - $(if $(CONFIG_TARGET_PREINIT_DISABLE_FAILSAFE), \ - rm -f $(1)/etc/banner.failsafe,) - - if [ -f $(TOPDIR)/feeds/luci/package.json ]; then \ - $(CP) ./luci2/* $(1)/; \ - fi endef ifneq ($(DUMP),1) diff --git a/package/base-files/files/bin/config_generate b/package/base-files/files/bin/config_generate index 52fd105fa..0867818d1 100755 --- a/package/base-files/files/bin/config_generate +++ b/package/base-files/files/bin/config_generate @@ -3,6 +3,7 @@ CFG=/etc/board.json . /usr/share/libubox/jshn.sh +. /lib/functions/ipv4.sh [ -s $CFG ] || /bin/board_detect || exit 1 [ -s /etc/config/network -a -s /etc/config/system ] && exit 0 @@ -40,18 +41,18 @@ generate_static_network() { uci -q batch <<-EOF delete network.loopback set network.loopback='interface' - set network.loopback.ifname='lo' + set network.loopback.device='lo' set network.loopback.proto='static' - set network.loopback.ipaddr='127.0.0.1' - set network.loopback.netmask='255.0.0.0' + add_list network.loopback.ipaddr='127.0.0.1/8' + delete network.globals + set network.globals='globals' + set network.globals.dhcp_default_duid='auto' EOF - [ -e /proc/sys/net/ipv6 ] && { - uci -q batch <<-EOF - delete network.globals - set network.globals='globals' - set network.globals.ula_prefix='auto' - EOF - } + [ -e /proc/sys/net/ipv6 ] && { + uci -q batch <<-EOF + set network.globals.ula_prefix='auto' + EOF + } if json_is_a dsl object; then json_select dsl @@ -91,86 +92,102 @@ generate_static_network() { addr_offset=2 generate_network() { - local ports ifname macaddr protocol type ipaddr netmask vlan + local ports device macaddr protocol type ipaddr netmask vlan local bridge=$2 json_select network json_select "$1" + json_get_vars device macaddr metric protocol ipaddr netmask vlan json_get_values ports ports - json_get_vars ifname macaddr protocol ipaddr netmask vlan json_select .. json_select .. - [ -n "$ifname" -o -n "$ports" ] || return + [ -n "$device" -o -n "$ports" ] || return # Force bridge for "lan" as it may have other devices (e.g. wireless) # bridged [ "$1" = "lan" -a -z "$ports" ] && { - ports="$ifname" + ports="$device" } - [ -n "$ports" ] && { - type="bridge" - ifname="$ports" + [ -n "$ports" -a -z "$bridge" ] && { + uci -q batch <<-EOF + add network device + set network.@device[-1].name='br-$1' + set network.@device[-1].type='bridge' + EOF + for port in $ports; do uci add_list network.@device[-1].ports="$port"; done + [ -n "$macaddr" ] && { + for port in $ports; do + uci -q batch <<-EOF + add network device + set network.@device[-1].name='$port' + set network.@device[-1].macaddr='$macaddr' + EOF + done + } + device=br-$1 + type= + macaddr="" } [ -n "$bridge" ] && { + [ -z "$ports" ] && ports="$device" if [ -z "$vlan" ]; then bridge_vlan_id=$((bridge_vlan_id + 1)) vlan=$bridge_vlan_id fi - generate_bridge_vlan $1 $bridge "$ifname" $vlan - ifname=$bridge.$vlan + generate_bridge_vlan $1 $bridge "$ports" $vlan + device=$bridge.$vlan type="" } + if [ -n "$macaddr" ]; then + uci -q batch <<-EOF + add network device + set network.@device[-1].name='$device' + set network.@device[-1].macaddr='$macaddr' + EOF + fi + uci -q batch <<-EOF delete network.$1 set network.$1='interface' set network.$1.type='$type' - set network.$1.ifname='$ifname' + set network.$1.device='$device' + set network.$1.metric='$metric' set network.$1.proto='none' EOF - if [ -n "$macaddr" ]; then - for name in $ifname; do - uci -q batch <<-EOF - delete network.$1_${name/./_}_dev - set network.$1_${name/./_}_dev='device' - set network.$1_${name/./_}_dev.name='$name' - set network.$1_${name/./_}_dev.macaddr='$macaddr' - EOF - done - fi - case "$protocol" in static) - local ipad + local ipad netm prefix case "$1" in lan) ipad=${ipaddr:-"192.168.1.1"} ;; *) ipad=${ipaddr:-"192.168.$((addr_offset++)).1"} ;; esac netm=${netmask:-"255.255.255.0"} + str2ip netm "$netm" + netmask2prefix prefix "$netm" uci -q batch <<-EOF set network.$1.proto='static' - set network.$1.ipaddr='$ipad' - set network.$1.netmask='$netm' + add_list network.$1.ipaddr='$ipad/$prefix' EOF [ -e /proc/sys/net/ipv6 ] && uci set network.$1.ip6assign='60' ;; dhcp) # fixup IPv6 slave interface if parent is a bridge - [ "$type" = "bridge" ] && ifname="br-$1" + [ "$type" = "bridge" ] && device="br-$1" uci set network.$1.proto='dhcp' [ -e /proc/sys/net/ipv6 ] && { uci -q batch <<-EOF delete network.${1}6 set network.${1}6='interface' - set network.${1}6.ifname='$ifname' + set network.${1}6.device='$device' set network.${1}6.proto='dhcpv6' EOF } @@ -187,7 +204,7 @@ generate_network() { set network.$1.ipv6='1' delete network.${1}6 set network.${1}6='interface' - set network.${1}6.ifname='@${1}' + set network.${1}6.device='@${1}' set network.${1}6.proto='dhcpv6' EOF } @@ -297,9 +314,10 @@ generate_static_system() { delete system.@system[0] add system system set system.@system[-1].hostname='LEDE' - set system.@system[-1].timezone='UTC' + set system.@system[-1].timezone='GMT0' + set system.@system[-1].zonename='UTC' set system.@system[-1].ttylogin='0' - set system.@system[-1].log_size='64' + set system.@system[-1].log_size='128' set system.@system[-1].urandom_seed='0' delete system.ntp @@ -326,6 +344,11 @@ generate_static_system() { uci -q set "system.@system[-1].compat_version=1.0" fi + local timezone + if json_get_var timezone timezone; then + uci -q set "system.@system[-1].timezone=$timezone" + fi + if json_is_a ntpserver array; then local keys key json_get_keys keys ntpserver diff --git a/package/base-files/files/etc/hotplug.d/leds/00-init b/package/base-files/files/etc/hotplug.d/leds/00-init new file mode 100644 index 000000000..0303e2bc4 --- /dev/null +++ b/package/base-files/files/etc/hotplug.d/leds/00-init @@ -0,0 +1,3 @@ +#!/bin/sh + +[ "$ACTION" = "add" ] && /etc/init.d/led start "$DEVICENAME" diff --git a/package/base-files/files/etc/init.d/boot b/package/base-files/files/etc/init.d/boot index 749d9e971..3b9a80843 100755 --- a/package/base-files/files/etc/init.d/boot +++ b/package/base-files/files/etc/init.d/boot @@ -10,11 +10,13 @@ uci_apply_defaults() { cd /etc/uci-defaults || return 0 files="$(ls)" [ -z "$files" ] && return 0 - mkdir -p /tmp/.uci + applied="" for file in $files; do - ( . "./$(basename $file)" ) && rm -f "$file" + ( . "./$(basename $file)" ) && applied="$applied $file" done uci commit + sync + rm -f $applied } boot() { @@ -25,6 +27,8 @@ boot() { chmod 1777 /var/lock mkdir -p /var/log mkdir -p /var/run + ln -s /var/run /run + ln -s /var/lock /run/lock mkdir -p /var/state mkdir -p /var/tmp mkdir -p /tmp/.uci @@ -34,9 +38,9 @@ boot() { mkdir -p /tmp/resolv.conf.d touch /tmp/resolv.conf.d/resolv.conf.auto ln -sf /tmp/resolv.conf.d/resolv.conf.auto /tmp/resolv.conf - grep -q debugfs /proc/filesystems && /bin/mount -o noatime -t debugfs debugfs /sys/kernel/debug + grep -q debugfs /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime -t debugfs debugfs /sys/kernel/debug grep -q bpf /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime,mode=0700 -t bpf bpffs /sys/fs/bpf - grep -q pstore /proc/filesystems && /bin/mount -o noatime -t pstore pstore /sys/fs/pstore + grep -q pstore /proc/filesystems && /bin/mount -o nosuid,nodev,noexec,noatime -t pstore pstore /sys/fs/pstore [ "$FAILSAFE" = "true" ] && touch /tmp/.failsafe /sbin/kmodloader @@ -49,7 +53,7 @@ boot() { /bin/config_generate uci_apply_defaults sync - + # temporary hack until configd exists /sbin/reload_config } diff --git a/package/base-files/files/etc/init.d/done b/package/base-files/files/etc/init.d/done index 32d6118df..77d2721f7 100755 --- a/package/base-files/files/etc/init.d/done +++ b/package/base-files/files/etc/init.d/done @@ -5,6 +5,7 @@ START=95 boot() { mount_root done rm -f /sysupgrade.tgz && sync + rm -f /tmp/sysupgrade.tar && sync # process user commands [ -f /etc/rc.local ] && { diff --git a/package/base-files/files/etc/init.d/led b/package/base-files/files/etc/init.d/led index 08a1e6df3..79fdd452c 100755 --- a/package/base-files/files/etc/init.d/led +++ b/package/base-files/files/etc/init.d/led @@ -3,6 +3,43 @@ START=96 +extra_command "turnon" "Put the LEDs into their default state" +extra_command "turnoff" "Turn all LEDs off" +extra_command "blink" "Blink all LEDs" + +led_color_set() { + local cfg="$1" + local sysfs="$2" + + local max_b + local colors + local color + local multi_intensity + local value + local write + + [ -e /sys/class/leds/${sysfs}/multi_intensity ] || return + [ -e /sys/class/leds/${sysfs}/multi_index ] || return + + max_b="$(cat /sys/class/leds/${sysfs}/max_brightness)" + colors="$(cat /sys/class/leds/${sysfs}/multi_index | tr " " "\n")" + multi_intensity="" + for color in $colors; do + config_get value $1 "color_${color}" "0" + [ "$value" -gt 0 ] && write=1 + [ "$value" -gt "$max_b" ] && value="$max_b" + multi_intensity="${multi_intensity}${value} " + done + + # Check if any color is configured + [ "$write" = 1 ] || return + # Remove last whitespace + multi_intensity="${multi_intensity:0:-1}" + + echo "setting '${name}' led color to '${multi_intensity}'" + echo "${multi_intensity}" > /sys/class/leds/${sysfs}/multi_intensity +} + load_led() { local name local sysfs @@ -14,6 +51,7 @@ load_led() { local delayon local delayoff local interval + local brightness config_get sysfs $1 sysfs config_get name $1 name "$sysfs" @@ -30,6 +68,9 @@ load_led() { config_get message $1 message "" config_get gpio $1 gpio "0" config_get_bool inverted $1 inverted "0" + config_get brightness $1 brightness + + [ "$2" ] && [ "$sysfs" != "$2" ] && return # execute application led trigger [ -f "/usr/libexec/led-trigger/${trigger}" ] && { @@ -49,21 +90,31 @@ load_led() { [ -e /sys/class/leds/${sysfs}/brightness ] && { echo "setting up led ${name}" - printf "%s %s %d\n" \ + printf "%s %s %d" \ "$sysfs" \ "$(sed -ne 's/^.*\[\(.*\)\].*$/\1/p' /sys/class/leds/${sysfs}/trigger)" \ "$(cat /sys/class/leds/${sysfs}/brightness)" \ >> /var/run/led.state + # Save default color if supported + [ -e /sys/class/leds/${sysfs}/multi_intensity ] && { + printf " %s" \ + "$(sed 's/\ /:/g' /sys/class/leds/${sysfs}/multi_intensity)" \ + >> /var/run/led.state + } + printf "\n" >> /var/run/led.state [ "$default" = 0 ] && echo 0 >/sys/class/leds/${sysfs}/brightness + [ "$default" = 1 ] && { + [ -z "$brightness" ] && brightness="$(cat /sys/class/leds/${sysfs}/max_brightness)" + echo "$brightness" > /sys/class/leds/${sysfs}/brightness + } + + led_color_set "$1" "$sysfs" + echo $trigger > /sys/class/leds/${sysfs}/trigger 2> /dev/null ret="$?" - - [ $default = 1 ] && - cat /sys/class/leds/${sysfs}/max_brightness > /sys/class/leds/${sysfs}/brightness - [ $ret = 0 ] || { echo >&2 "Skipping trigger '$trigger' for led '$name' due to missing kernel module" return 1 @@ -80,7 +131,7 @@ load_led() { [ -e "/sys/class/leds/${sysfs}/$m" ] && \ echo 1 > /sys/class/leds/${sysfs}/$m done - echo $interval > /sys/class/leds/${sysfs}/interval + echo $interval > /sys/class/leds/${sysfs}/interval 2>/dev/null } ;; @@ -125,21 +176,55 @@ load_led() { } } +turnoff() { + for led in `ls /sys/class/leds/`; do + echo 0 > /sys/class/leds/$led/brightness + done +} + +turnon() { + turnoff + . /etc/diag.sh + set_state done + start +} + +blink() { + for led in `ls /sys/class/leds/`; do + echo 0 > /sys/class/leds/$led/brightness + echo timer > /sys/class/leds/$led/trigger + done +} + start() { + [ "$(uci -q get system.@system[-1].leds_off)" = '1' ] && { + turnoff + exit 0 + } [ -e /sys/class/leds/ ] && { [ -s /var/run/led.state ] && { - local led trigger brightness - while read led trigger brightness; do + local led trigger brightness color + while read led trigger brightness color; do + [ "$1" ] && [ "$1" != "$led" ] && continue [ -e "/sys/class/leds/$led/trigger" ] && \ echo "$trigger" > "/sys/class/leds/$led/trigger" [ -e "/sys/class/leds/$led/brightness" ] && \ echo "$brightness" > "/sys/class/leds/$led/brightness" + + [ -e "/sys/class/leds/$led/multi_intensity" ] && \ + echo "$color" | sed 's/:/\ /g' > \ + "/sys/class/leds/$led/multi_intensity" done < /var/run/led.state - rm /var/run/led.state + if [ "$1" ]; then + grep -v "^$1 " /var/run/led.state > /var/run/led.state.new + mv /var/run/led.state.new /var/run/led.state + else + rm /var/run/led.state + fi } config_load system - config_foreach load_led led + config_foreach load_led led "$1" } } diff --git a/package/base-files/files/etc/init.d/system b/package/base-files/files/etc/init.d/system index c651ed500..9e3bfc5ae 100755 --- a/package/base-files/files/etc/init.d/system +++ b/package/base-files/files/etc/init.d/system @@ -9,8 +9,8 @@ validate_system_section() { 'hostname:string:LEDE' \ 'conloglevel:uinteger' \ 'buffersize:uinteger' \ - 'timezone:string:UTC' \ - 'zonename:string' + 'timezone:string:GMT0' \ + 'zonename:string:UTC' } system_config() { diff --git a/package/base-files/files/etc/uci-defaults/11_network-migrate-bridges b/package/base-files/files/etc/uci-defaults/11_network-migrate-bridges new file mode 100644 index 000000000..a9dece418 --- /dev/null +++ b/package/base-files/files/etc/uci-defaults/11_network-migrate-bridges @@ -0,0 +1,49 @@ +. /lib/functions.sh + +migrate_ports() { + local config="$1" + local type ports ifname + + config_get type "$config" type + [ "$type" != "bridge" ] && return + + config_get ports "$config" ports + [ -n "$ports" ] && return + + config_get ifname "$config" ifname + [ -z "$ifname" ] && return + + for port in $ifname; do + uci add_list network.$config.ports="$port" + done + uci delete network.$config.ifname +} + +migrate_bridge() { + local config="$1" + local type ifname + + config_get type "$config" type + [ "$type" != "bridge" ] && return + + config_get ifname "$config" ifname + + uci -q batch <<-EOF + add network device + set network.@device[-1].name='br-$config' + set network.@device[-1].type='bridge' + EOF + for port in $ifname; do + uci add_list network.@device[-1].ports="$port" + done + + uci -q batch <<-EOF + delete network.$config.type + delete network.$config.ifname + set network.$config.device='br-$config' + EOF +} + +config_load network +config_foreach migrate_ports device +config_foreach migrate_bridge interface diff --git a/package/base-files/files/etc/uci-defaults/12_network-generate-ula b/package/base-files/files/etc/uci-defaults/12_network-generate-ula index 19d7ed7f2..060d0ef64 100644 --- a/package/base-files/files/etc/uci-defaults/12_network-generate-ula +++ b/package/base-files/files/etc/uci-defaults/12_network-generate-ula @@ -1,11 +1,7 @@ [ "$(uci -q get network.globals.ula_prefix)" != "auto" ] && exit 0 -r1=$(dd if=/dev/urandom bs=1 count=1 |hexdump -e '1/1 "%02x"') -r2=$(dd if=/dev/urandom bs=2 count=1 |hexdump -e '2/1 "%02x"') -r3=$(dd if=/dev/urandom bs=2 count=1 |hexdump -e '2/1 "%02x"') - uci -q batch <<-EOF >/dev/null - set network.globals.ula_prefix=fd$r1:$r2:$r3::/48 + set network.globals.ula_prefix="$(hexdump -vn 5 -e '"fd" 1/1 "%02x:" 2/2 "%x:"' /dev/urandom):/48" commit network EOF diff --git a/package/base-files/files/etc/uci-defaults/13_fix-group-user b/package/base-files/files/etc/uci-defaults/13_fix-group-user index 74f501e8f..c5cc74e1a 100644 --- a/package/base-files/files/etc/uci-defaults/13_fix-group-user +++ b/package/base-files/files/etc/uci-defaults/13_fix-group-user @@ -1,5 +1,8 @@ . /lib/functions.sh +# Skip if we don't have /usr/lib/opkg/info (APK installation) +[ -d /usr/lib/opkg/info ] || exit 0 + for file in $(grep -sl Require-User /usr/lib/opkg/info/*.control); do file="${file##*/}" file="${file%.control}" diff --git a/package/base-files/files/etc/uci-defaults/14_network-generate-clientid b/package/base-files/files/etc/uci-defaults/14_network-generate-clientid new file mode 100644 index 000000000..70da185c2 --- /dev/null +++ b/package/base-files/files/etc/uci-defaults/14_network-generate-clientid @@ -0,0 +1,9 @@ +[ "$(uci -q get network.globals.dhcp_default_duid)" != "auto" ] && exit 0 + +uci -q batch <<-EOF >/dev/null + # DUID-UUID - RFC6355 + set network.globals.dhcp_default_duid="$(hexdump -vn 16 -e '"0004" 2/2 "%x"' /dev/urandom)" + commit network +EOF + +exit 0 diff --git a/package/base-files/files/etc/uci-defaults/50-root-passwd b/package/base-files/files/etc/uci-defaults/50-root-passwd new file mode 100644 index 000000000..f0bb519ae --- /dev/null +++ b/package/base-files/files/etc/uci-defaults/50-root-passwd @@ -0,0 +1,18 @@ +. /usr/share/libubox/jshn.sh + +json_init +json_load "$(cat /etc/board.json)" + +if json_is_a credentials object; then + json_select credentials + json_get_vars root_password_hash root_password_hash + if [ -n "$root_password_hash" ]; then + sed -i "s|^root:[^:]*|root:$root_password_hash|g" /etc/shadow + fi + + json_get_vars root_password_plain root_password_plain + if [ -n "$root_password_plain" ]; then + (echo "$root_password_plain"; sleep 1; echo "$root_password_plain") | passwd root + fi + json_select .. +fi diff --git a/package/base-files/files/lib/functions.sh b/package/base-files/files/lib/functions.sh index 2d79d47db..5597cf655 100644 --- a/package/base-files/files/lib/functions.sh +++ b/package/base-files/files/lib/functions.sh @@ -32,6 +32,30 @@ xor() { printf "%0${retlen}x" "$ret" } +data_2bin() { + local data=$1 + local len=${#1} + local bin_data + + for i in $(seq 0 2 $(($len - 1))); do + bin_data="${bin_data}\x${data:i:2}" + done + + echo -ne $bin_data +} + +data_2xor_val() { + local data=$1 + local len=${#1} + local xor_data + + for i in $(seq 0 4 $(($len - 1))); do + xor_data="${xor_data}${data:i:4} " + done + + echo -n ${xor_data:0:-1} +} + append() { local var="$1" local value="$2" @@ -40,6 +64,14 @@ append() { eval "export ${NO_EXPORT:+-n} -- \"$var=\${$var:+\${$var}\${value:+\$sep}}\$value\"" } +prepend() { + local var="$1" + local value="$2" + local sep="${3:- }" + + eval "export ${NO_EXPORT:+-n} -- \"$var=\$value\${$var:+\${sep}\${$var}}\"" +} + list_contains() { local var="$1" local str="$2" @@ -181,6 +213,7 @@ default_prerm() { local root="${IPKG_INSTROOT}" local pkgname="$(basename ${1%.*})" local ret=0 + local filelist="${root}/usr/lib/opkg/info/${pkgname}.list" if [ -f "$root/usr/lib/opkg/info/${pkgname}.prerm-pkg" ]; then ( . "$root/usr/lib/opkg/info/${pkgname}.prerm-pkg" ) @@ -188,7 +221,7 @@ default_prerm() { fi local shell="$(command -v bash)" - for i in $(grep -s "^/etc/init.d/" "$root/usr/lib/opkg/info/${pkgname}.list"); do + for i in $(grep -s "^/etc/init.d/" "$filelist"); do if [ -n "$root" ]; then ${shell:-/bin/sh} "$root/etc/rc.common" "$root$i" disable else @@ -203,7 +236,7 @@ default_prerm() { } add_group_and_user() { - local pkgname="$1" + local pkgname="$(basename ${1%.*})" local rusers="$(sed -ne 's/^Require-User: *//p' $root/usr/lib/opkg/info/${pkgname}.control 2>/dev/null)" if [ -n "$rusers" ]; then @@ -293,7 +326,7 @@ default_postinst() { fi local shell="$(command -v bash)" - for i in $(grep -s "^/etc/init.d/" "$root$filelist"); do + for i in $(grep -s "^/etc/init.d/" "$filelist"); do if [ -n "$root" ]; then ${shell:-/bin/sh} "$root/etc/rc.common" "$root$i" enable else @@ -349,7 +382,7 @@ find_mmc_part() { fi for DEVNAME in /sys/block/$ROOTDEV/mmcblk*p*; do - PARTNAME="$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=')" + PARTNAME="$(grep PARTNAME ${DEVNAME}/uevent | cut -f2 -d'=' 2>/dev/null)" [ "$PARTNAME" = "$1" ] && echo "/dev/$(basename $DEVNAME)" && return 0 done } @@ -438,4 +471,4 @@ cmdline_get_var() { done } -[ -z "$IPKG_INSTROOT" ] && [ -f /lib/config/uci.sh ] && . /lib/config/uci.sh +[ -z "$IPKG_INSTROOT" ] && [ -f /lib/config/uci.sh ] && . /lib/config/uci.sh || true diff --git a/package/base-files/files/lib/functions/ipv4.sh b/package/base-files/files/lib/functions/ipv4.sh new file mode 100644 index 000000000..d0b93dbcb --- /dev/null +++ b/package/base-files/files/lib/functions/ipv4.sh @@ -0,0 +1,268 @@ +uint_max=4294967295 + +d_10_0_0_0=167772160 +d_10_255_255_255=184549375 + +d_172_16_0_0=2886729728 +d_172_31_255_255=2887778303 + +d_192_168_0_0=3232235520 +d_192_168_255_255=3232301055 + +d_169_254_0_0=2851995648 +d_169_254_255_255=2852061183 + +d_127_0_0_0=2130706432 +d_127_255_255_255=2147483647 + +d_224_0_0_0=3758096384 +d_239_255_255_255=4026531839 + +# check that $1 is only base 10 digits, and that it doesn't +# exceed 2^32-1 +assert_uint32() { + local __n="$1" + + if [ -z "$__n" -o -n "${__n//[0-9]/}" ]; then + printf "Not a decimal integer (%s)\n" "$__n ">&2 + return 1 + fi + + if [ "$__n" -gt $uint_max ]; then + printf "Out of range (%s)\n" "$__n" >&2 + return 1 + fi + + if [ "$((__n + 0))" != "$__n" ]; then + printf "Not normalized notation (%s)\n" "$__n" >&2 + return 1 + fi + + return 0 +} + +# return a count of the number of bits set in $1 +bitcount() { + local __var="$1" __c="$2" + assert_uint32 "$__c" || return 1 + + __c=$((((__c >> 1) & 0x55555555) + (__c & 0x55555555))) + __c=$((((__c >> 2) & 0x33333333) + (__c & 0x33333333))) + __c=$((((__c >> 4) & 0x0f0f0f0f) + (__c & 0x0f0f0f0f))) + __c=$((((__c >> 8) & 0x00ff00ff) + (__c & 0x00ff00ff))) + __c=$((((__c >> 16) & 0x0000ffff) + (__c & 0x0000ffff))) + + export -- "$__var=$__c" +} + +# tedious but portable with busybox's limited shell +# we check each octet to be in the range of 0..255, +# and also make sure there's no extaneous characters. +str2ip() { + local __var="$1" __ip="$2" __n __val=0 + + case "$__ip" in + [0-9].*) + __n="${__ip:0:1}" + __ip="${__ip:2}" + ;; + [1-9][0-9].*) + __n="${__ip:0:2}" + __ip="${__ip:3}" + ;; + 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*) + __n="${__ip:0:3}" + __ip="${__ip:4}" + ;; + *) + printf "Not a dotted quad (%s)\n" "$2" >&2 + return 1 + ;; + esac + + __val=$((__n << 24)) + + case "$__ip" in + [0-9].*) + __n="${__ip:0:1}" + __ip="${__ip:2}" + ;; + [1-9][0-9].*) + __n="${__ip:0:2}" + __ip="${__ip:3}" + ;; + 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*) + __n="${__ip:0:3}" + __ip="${__ip:4}" + ;; + *) + printf "Not a dotted quad (%s)\n" "$2" >&2 + return 1 + ;; + esac + + __val=$((__val + (__n << 16))) + + case "$__ip" in + [0-9].*) + __n="${__ip:0:1}" + __ip="${__ip:2}" + ;; + [1-9][0-9].*) + __n="${__ip:0:2}" + __ip="${__ip:3}" + ;; + 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*) + __n="${__ip:0:3}" + __ip="${__ip:4}" + ;; + *) + printf "Not a dotted quad (%s)\n" "$2" >&2 + return 1 + ;; + esac + + __val=$((__val + (__n << 8))) + + case "$__ip" in + [0-9]) + __n="${__ip:0:1}" + __ip="${__ip:1}" + ;; + [1-9][0-9]) + __n="${__ip:0:2}" + __ip="${__ip:2}" + ;; + 1[0-9][0-9]|2[0-4][0-9]|25[0-5]) + __n="${__ip:0:3}" + __ip="${__ip:3}" + ;; + *) + printf "Not a dotted quad (%s)\n" "$2" >&2 + return 1 + ;; + esac + + __val=$((__val + __n)) + + if [ -n "$__ip" ]; then + printf "Not a dotted quad (%s)\n" "$2" >&2 + return 1 + fi + + export -- "$__var=$__val" + return 0 +} + +# convert back from an integer to dotted-quad. +ip2str() { + local __var="$1" __n="$2" + assert_uint32 "$__n" || return 1 + + export -- "$__var=$((__n >> 24)).$(((__n >> 16) & 255)).$(((__n >> 8) & 255)).$((__n & 255))" +} + +# convert prefix into an integer bitmask +prefix2netmask() { + local __var="$1" __n="$2" + assert_uint32 "$__n" || return 1 + + if [ "$__n" -gt 32 ]; then + printf "Prefix out-of-range (%s)" "$__n" >&2 + return 1 + fi + + export -- "$__var=$(((~(uint_max >> __n)) & uint_max))" +} + +_is_contiguous() { + local __x="$1" # no checking done + local __y=$((~__x & uint_max)) + local __z=$(((__y + 1) & uint_max)) + + [ $((__z & __y)) -eq 0 ] +} + +# check argument as being contiguous upper bits (and yes, +# 0 doesn't have any discontiguous bits). +is_contiguous() { + local __var="$1" __x="$2" __val=0 + assert_uint32 "$__x" || return 1 + + local __y=$((~__x & uint_max)) + local __z=$(((__y + 1) & uint_max)) + + [ $((__z & __y)) -eq 0 ] && __val=1 + + export -- "$__var=$__val" +} + +# convert mask to prefix, validating that it's a conventional +# (contiguous) netmask. +netmask2prefix() { + local __var="$1" __n="$2" __cont __bits + assert_uint32 "$__n" || return 1 + + is_contiguous __cont "$__n" || return 1 + if [ $__cont -eq 0 ]; then + printf "Not a contiguous netmask (%08x)\n" "$__n" >&2 + return 1 + fi + + bitcount __bits "$__n" # already checked + + export -- "$__var=$__bits" +} + +# check the argument as being an rfc-1918 address +is_rfc1918() { + local __var="$1" __x="$2" __val=0 + assert_uint32 "$__x" || return 1 + + if [ $d_10_0_0_0 -le $__x ] && [ $__x -le $d_10_255_255_255 ]; then + __val=1 + elif [ $d_172_16_0_0 -le $__x ] && [ $__x -le $d_172_31_255_255 ]; then + __val=1 + elif [ $d_192_168_0_0 -le $__x ] && [ $__x -le $d_192_168_255_255 ]; then + __val=1 + fi + + export -- "$__var=$__val" +} + +# check the argument as being an rfc-3927 address +is_rfc3927() { + local __var="$1" __x="$2" __val=0 + assert_uint32 "$__x" || return 1 + + if [ $d_169_254_0_0 -le $__x ] && [ $__x -le $d_169_254_255_255 ]; then + __val=1 + fi + + export -- "$__var=$__val" +} + +# check the argument as being an rfc-1122 loopback address +is_loopback() { + local __var="$1" __x="$2" __val=0 + assert_uint32 "$__x" || return 1 + + if [ $d_127_0_0_0 -le $__x ] && [ $__x -le $d_127_255_255_255 ]; then + __val=1 + fi + + export -- "$__var=$__val" +} + +# check the argument as being a multicast address +is_multicast() { + local __var="$1" __x="$2" __val=0 + assert_uint32 "$__x" || return 1 + + if [ $d_224_0_0_0 -le $__x ] && [ $__x -le $d_239_255_255_255 ]; then + __val=1 + fi + + export -- "$__var=$__val" +} + diff --git a/package/base-files/files/lib/functions/system.sh b/package/base-files/files/lib/functions/system.sh index e6ed0c08e..9ebc4aaa7 100644 --- a/package/base-files/files/lib/functions/system.sh +++ b/package/base-files/files/lib/functions/system.sh @@ -315,3 +315,10 @@ macaddr_canonicalize() { dt_is_enabled() { grep -q okay "/proc/device-tree/$1/status" } + +get_linux_version() { + local ver=$(uname -r) + local minor=${ver%\.*} + + printf "%d%02d%03d" ${ver%%\.*} ${minor#*\.} ${ver##*\.} 2>/dev/null +} diff --git a/package/base-files/files/lib/functions/uci-defaults.sh b/package/base-files/files/lib/functions/uci-defaults.sh index 605f7463c..f77ce4ab2 100644 --- a/package/base-files/files/lib/functions/uci-defaults.sh +++ b/package/base-files/files/lib/functions/uci-defaults.sh @@ -39,7 +39,7 @@ ucidef_set_interface() { [ -n "$opt" -a -n "$val" ] || break - [ "$opt" = "ifname" -a "$val" != "${val/ //}" ] && { + [ "$opt" = "device" -a "$val" != "${val/ //}" ] && { json_select_array "ports" for e in $val; do json_add_string "" "$e"; done json_close_array @@ -79,11 +79,11 @@ ucidef_set_compat_version() { } ucidef_set_interface_lan() { - ucidef_set_interface "lan" ifname "$1" protocol "${2:-static}" + ucidef_set_interface "lan" device "$1" protocol "${2:-static}" } ucidef_set_interface_wan() { - ucidef_set_interface "wan" ifname "$1" protocol "${2:-dhcp}" + ucidef_set_interface "wan" device "$1" protocol "${2:-dhcp}" } ucidef_set_interfaces_lan_wan() { @@ -107,7 +107,7 @@ ucidef_set_bridge_mac() { } _ucidef_set_network_device_common() { - json_select_object "network-device" + json_select_object "network_device" json_select_object "${1}" json_add_string "${2}" "${3}" json_select .. @@ -122,6 +122,11 @@ ucidef_set_network_device_path() { _ucidef_set_network_device_common $1 path $2 } +ucidef_set_network_device_path_port() { + _ucidef_set_network_device_common $1 path $2 + _ucidef_set_network_device_common $1 port $3 +} + ucidef_set_network_device_gro() { _ucidef_set_network_device_common $1 gro $2 } @@ -217,14 +222,14 @@ _ucidef_finish_switch_roles() { json_select_object "$role" # attach previous interfaces (for multi-switch devices) - json_get_var devices ifname + json_get_var devices device if ! list_contains devices "$device"; then devices="${devices:+$devices }$device" fi json_select .. json_select .. - ucidef_set_interface "$role" ifname "$devices" + ucidef_set_interface "$role" device "$devices" done } @@ -642,6 +647,92 @@ ucidef_set_hostname() { json_select .. } +ucidef_set_timezone() { + local timezone="$1" + json_select_object system + json_add_string timezone "$timezone" + json_select .. +} + +ucidef_set_wireless() { + local band="$1" + local ssid="$2" + local encryption="$3" + local key="$4" + + case "$band" in + all|2g|5g|6g) ;; + *) return;; + esac + [ -z "$ssid" ] && return + + json_select_object wlan + json_select_object defaults + json_select_object ssids + json_select_object "$band" + json_add_string ssid "$ssid" + [ -n "$encryption" ] && json_add_string encryption "$encryption" + [ -n "$key" ] && json_add_string key "$key" + json_select .. + json_select .. + json_select .. + json_select .. +} + +ucidef_set_country() { + local country="$1" + + json_select_object wlan + json_select_object defaults + json_add_string country "$country" + json_select .. + json_select .. +} + +ucidef_set_wireless_mac_count() { + local band="$1" + local mac_count="$2" + + case "$band" in + 2g|5g|6g) ;; + *) return;; + esac + [ -z "$mac_count" ] && return + + json_select_object wlan + json_select_object defaults + json_select_object ssids + json_select_object "$band" + json_add_string mac_count "$mac_count" + json_select .. + json_select .. + json_select .. + json_select .. +} + +ucidef_set_root_password_plain() { + local passwd="$1" + json_select_object credentials + json_add_string root_password_plain "$passwd" + json_select .. +} + +ucidef_set_root_password_hash() { + local passwd="$1" + json_select_object credentials + json_add_string root_password_hash "$passwd" + json_select .. +} + +ucidef_set_ssh_authorized_key() { + local ssh_key="$1" + json_select_object credentials + json_select_array ssh_authorized_keys + json_add_string "" "$ssh_key" + json_select .. + json_select .. +} + ucidef_set_ntpserver() { local server @@ -680,6 +771,27 @@ ucidef_add_wlan() { ucidef_wlan_idx="$((ucidef_wlan_idx + 1))" } +ucidef_set_interface_netdev_range() { + local interface="$1" + local base_netdev="$2" + local start="$3" + local stop="$4" + local netdevs + local i + + if [ "$stop" -ge "$start" ]; then + i="$start" + netdevs="$base_netdev$i" + + while [ "$i" -lt "$stop" ]; do + i=$((i + 1)) + netdevs="$netdevs $base_netdev$i" + done + + ucidef_set_interface "$interface" device "$netdevs" + fi +} + board_config_update() { json_init [ -f ${CFG} ] && json_load "$(cat ${CFG})" diff --git a/package/base-files/files/lib/preinit/10_indicate_preinit b/package/base-files/files/lib/preinit/10_indicate_preinit index 1996ca5ee..12f8fc2e2 100644 --- a/package/base-files/files/lib/preinit/10_indicate_preinit +++ b/package/base-files/files/lib/preinit/10_indicate_preinit @@ -63,6 +63,35 @@ preinit_config_switch() { json_select .. } +preinit_config_port() { + local original + local dev_port + + local netdev="$1" + local path="$2" + local port="$3" + + [ -d "/sys/devices/$path/net" ] || return + + if [ -z "$port" ]; then + original="$(ls "/sys/devices/$path/net" | head -1)" + else + for device in /sys/devices/$path/net/*; do + dev_port="$(cat "$device/dev_port")" + if [ "$dev_port" = "$port" ]; then + original="${device##*/}" + break + fi + done + + [ -z "$original" ] && return + fi + + [ "$netdev" = "$original" ] && return + + ip link set "$original" name "$netdev" +} + preinit_config_board() { /bin/board_detect /tmp/board.json @@ -73,16 +102,50 @@ preinit_config_board() { json_init json_load "$(cat /tmp/board.json)" + # Find the current highest eth* + max_eth=$(grep -o '^ *eth[0-9]*:' /proc/net/dev | tr -dc '[0-9]\n' | sort -n | tail -1) + # Find and move netdevs using eth*s we are configuring + json_get_keys keys "network_device" + for netdev in $keys; do + json_select "network_device" + json_select "$netdev" + json_get_vars path path + if [ -n "$path" -a -h "/sys/class/net/$netdev" ]; then + ip link set "$netdev" down + ip link set "$netdev" name eth$((++max_eth)) + fi + json_select .. + json_select .. + done + + # Move interfaces by path to their netdev name + json_get_keys keys "network_device" + for netdev in $keys; do + json_select "network_device" + json_select "$netdev" + json_get_vars path path + json_get_vars port port + [ -n "$path" ] && preinit_config_port "$netdev" "$path" "$port" + json_select .. + json_select .. + done + json_select network json_select "lan" - json_get_vars ifname + json_get_vars device + json_get_values ports ports json_select .. json_select .. - [ -n "$ifname" ] || return + [ -n "$device" -o -n "$ports" ] || return + + # swconfig uses $device and DSA uses ports + [ -z "$ports" ] && { + ports="$device" + } # only use the first one - ifname=${ifname%% *} + ifname=${ports%% *} if [ -x /sbin/swconfig ]; then # configure the switch, if present diff --git a/package/base-files/files/lib/preinit/30_failsafe_wait b/package/base-files/files/lib/preinit/30_failsafe_wait index 9ab2e8bd4..c792089ec 100644 --- a/package/base-files/files/lib/preinit/30_failsafe_wait +++ b/package/base-files/files/lib/preinit/30_failsafe_wait @@ -40,7 +40,7 @@ fs_wait_for_key () { rm -f $keypress_wait } & - local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')" + local consoles="$(cat /sys/class/tty/console/active)" [ -n "$consoles" ] || consoles=console for console in $consoles; do [ -c "/dev/$console" ] || continue @@ -78,6 +78,9 @@ fs_wait_for_key () { keypressed=1 [ "$(cat $keypress_true)" = "true" ] && keypressed=0 + trap - INT + trap - USR1 + rm -f $keypress_true rm -f $keypress_wait rm -f $keypress_sec diff --git a/package/base-files/files/lib/preinit/80_mount_root b/package/base-files/files/lib/preinit/80_mount_root index 1db751754..36d66b970 100644 --- a/package/base-files/files/lib/preinit/80_mount_root +++ b/package/base-files/files/lib/preinit/80_mount_root @@ -14,8 +14,27 @@ missing_lines() { IFS="$oIFS" } +# Rootfs mount options can be passed by declaring in the kernel +# cmdline as much options as needed prefixed with "rootfs_mount_options." +# +# Example: +# rootfs_mount_options.compress_algorithm=zstd rootfs_mount_options.noinline_data +# +compose_rootfs_mount_options() { + local mount_options + local cmdlinevar + + for cmdlinevar in $(cat /proc/cmdline); do + if [ "$cmdlinevar" != "${cmdlinevar#rootfs_mount_options\.}" ]; then + append mount_options "${cmdlinevar#rootfs_mount_options\.}" + fi + done + + echo $mount_options +} + do_mount_root() { - mount_root + mount_root start "$(compose_rootfs_mount_options)" boot_run_hook preinit_mount_root [ ! -f /etc/bench.log ] && touch /etc/bench.log [ -f /sysupgrade.tgz -o -f /tmp/sysupgrade.tar ] && { diff --git a/package/base-files/files/lib/preinit/99_10_failsafe_login b/package/base-files/files/lib/preinit/99_10_failsafe_login index 6f4af3f28..cd5c8e37d 100644 --- a/package/base-files/files/lib/preinit/99_10_failsafe_login +++ b/package/base-files/files/lib/preinit/99_10_failsafe_login @@ -2,7 +2,7 @@ # Copyright (C) 2010 Vertical Communications failsafe_shell() { - local consoles="$(sed -e 's/ /\n/g' /proc/cmdline | grep '^console=' | sed -e 's/^console=//' -e 's/,.*//')" + local consoles="$(cat /sys/class/tty/console/active)" [ -n "$consoles" ] || consoles=console for console in $consoles; do [ -c "/dev/$console" ] && while true; do diff --git a/package/base-files/files/lib/upgrade/tar.sh b/package/base-files/files/lib/upgrade/tar.sh new file mode 100644 index 000000000..a9d1d559e --- /dev/null +++ b/package/base-files/files/lib/upgrade/tar.sh @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: GPL-2.0-or-later OR MIT + +# Example usage: +# +# { +# tar_print_member "date.txt" "It's $(date +"%Y")" +# tar_print_trailer +# } > test.tar + +__tar_print_padding() { + dd if=/dev/zero bs=1 count=$1 2>/dev/null +} + +tar_print_member() { + local name="$1" + local content="$2" + local mtime="${3:-$(date +%s)}" + local mode=644 + local uid=0 + local gid=0 + local size=${#content} + local type=0 + local link="" + local username="root" + local groupname="root" + + # 100 byte of padding bytes, using 0x01 since the shell does not tolerate null bytes in strings + local pad=$'\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1' + + # validate name (strip leading slash if present) + name=${name#/} + + # truncate string header values to their maximum length + name=${name:0:100} + link=${link:0:100} + username=${username:0:32} + groupname=${groupname:0:32} + + # construct header part before checksum field + local header1="${name}${pad:0:$((100 - ${#name}))}" + header1="${header1}$(printf '%07d\1' $mode)" + header1="${header1}$(printf '%07o\1' $uid)" + header1="${header1}$(printf '%07o\1' $gid)" + header1="${header1}$(printf '%011o\1' $size)" + header1="${header1}$(printf '%011o\1' $mtime)" + + # construct header part after checksum field + local header2="$(printf '%d' $type)" + header2="${header2}${link}${pad:0:$((100 - ${#link}))}" + header2="${header2}ustar ${pad:0:1}" + header2="${header2}${username}${pad:0:$((32 - ${#username}))}" + header2="${header2}${groupname}${pad:0:$((32 - ${#groupname}))}" + + # calculate checksum over header fields + local checksum=0 + for byte in $(printf '%s%8s%s' "$header1" "" "$header2" | tr '\1' '\0' | hexdump -ve '1/1 "%u "'); do + checksum=$((checksum + byte)) + done + + # print member header, padded to 512 byte + printf '%s%06o\0 %s' "$header1" $checksum "$header2" | tr '\1' '\0' + __tar_print_padding 183 + + # print content data, padded to multiple of 512 byte + printf "%s" "$content" + __tar_print_padding $((512 - (size % 512))) +} + +tar_print_trailer() { + __tar_print_padding 1024 +} diff --git a/package/base-files/files/sbin/sysupgrade b/package/base-files/files/sbin/sysupgrade index 931509130..4099c2b25 100755 --- a/package/base-files/files/sbin/sysupgrade +++ b/package/base-files/files/sbin/sysupgrade @@ -24,6 +24,8 @@ export NEED_IMAGE= export HELP=0 export FORCE=0 export TEST=0 +export USE_CURR_PART=0 +export ADD_PROVISIONING=0 export UMOUNT_ETCBACKUP_DIR=0 # parse options @@ -36,12 +38,14 @@ while [ -n "$1" ]; do -c) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/etc;; -o) export SAVE_OVERLAY=1 SAVE_OVERLAY_PATH=/;; -p) export SAVE_PARTITIONS=0;; + -P) export ADD_PROVISIONING=1;; -k) export SAVE_INSTALLED_PKGS=1;; -u) export SKIP_UNCHANGED=1;; -b|--create-backup) export CONF_BACKUP="$2" NEED_IMAGE=1; shift;; -r|--restore-backup) export CONF_RESTORE="$2" NEED_IMAGE=1; shift;; -l|--list-backup) export CONF_BACKUP_LIST=1;; -f) export CONF_IMAGE="$2"; shift;; + -s) export USE_CURR_PART=1;; -F|--force) export FORCE=1;; -T|--test) export TEST=1;; -h|--help) export HELP=1; break;; @@ -60,12 +64,10 @@ export CONF_TAR=/tmp/sysupgrade.tgz export ETCBACKUP_DIR=/etc/backup export INSTALLED_PACKAGES=${ETCBACKUP_DIR}/installed_packages.txt -IMAGE="$1" - -[ -z "$IMAGE" -a -z "$NEED_IMAGE" -a $CONF_BACKUP_LIST -eq 0 -o $HELP -gt 0 ] && { +print_help() { cat <...] - $0 [-q] [-i] [-c] [-u] [-o] [-k] + $0 [-q] [-i] [-c] [-u] [-o] [-k] [-P] upgrade-option: -f restore configuration from .tar.gz (file or url) @@ -78,6 +80,9 @@ upgrade-option: -p do not attempt to restore the partition table after flash. -k include in backup a list of current installed packages at $INSTALLED_PACKAGES + -s stay on current partition (for dual firmware devices) + -P create provisioning partition to keep sensitive data across + factory resets. -T | --test Verify image and config .tar.gz but do not actually flash. -F | --force @@ -102,9 +107,20 @@ backup-command: sysupgrade -b. Does not create a backup file. EOF - exit 1 } +IMAGE="$1" + +if [ $HELP -gt 0 ]; then + print_help + exit 0 +fi + +if [ -z "$IMAGE" -a -z "$NEED_IMAGE" -a $CONF_BACKUP_LIST -eq 0 ]; then + print_help + exit 1 +fi + [ -n "$IMAGE" -a -n "$NEED_IMAGE" ] && { cat <<-EOF -b|--create-backup and -r|--restore-backup do not perform a firmware upgrade. @@ -143,7 +159,7 @@ list_static_conffiles() { \( -type f -o -type l \) $filter 2>/dev/null } -add_conffiles() { +build_list_of_backup_config_files() { local file="$1" ( list_static_conffiles "$find_filter"; list_changed_conffiles ) | @@ -151,7 +167,7 @@ add_conffiles() { return 0 } -add_overlayfiles() { +build_list_of_backup_overlay_files() { local file="$1" local packagesfiles=$1.packagesfiles @@ -203,12 +219,12 @@ add_overlayfiles() { if [ $SAVE_OVERLAY = 1 ]; then [ ! -d /overlay/upper/etc ] && { - echo "Cannot find '/overlay/upper/etc', required for '-c'" >&2 + echo "Cannot find '/overlay/upper/etc', required for '-c' or '-o'" >&2 exit 1 } - sysupgrade_init_conffiles="add_overlayfiles" + sysupgrade_init_conffiles="build_list_of_backup_overlay_files" else - sysupgrade_init_conffiles="add_conffiles" + sysupgrade_init_conffiles="build_list_of_backup_config_files" fi find_filter="" @@ -329,8 +345,9 @@ json_load "$(/usr/libexec/validate_firmware_image "$IMAGE")" || { exit 1 } json_get_var valid "valid" +json_get_var forceable "forceable" [ "$valid" -eq 0 ] && { - if [ $FORCE -eq 1 ]; then + if [ $FORCE -eq 1 ] && [ "$forceable" -eq 1 ]; then echo "Image check failed but --force given - will update anyway!" >&2 else echo "Image check failed." >&2 @@ -378,6 +395,8 @@ else json_add_string command "$COMMAND" json_add_object options json_add_int save_partitions "$SAVE_PARTITIONS" + json_add_int add_provisioning "$ADD_PROVISIONING" + [ $USE_CURR_PART -eq 1 ] && json_add_boolean use_curr_part 1 json_close_object ubus call system sysupgrade "$(json_dump)" diff --git a/package/base-files/files/usr/lib/os-release b/package/base-files/files/usr/lib/os-release index c39913d54..7682101dc 100644 --- a/package/base-files/files/usr/lib/os-release +++ b/package/base-files/files/usr/lib/os-release @@ -7,6 +7,7 @@ VERSION_ID="%v" HOME_URL="%u" BUG_URL="%b" SUPPORT_URL="%s" +FIRMWARE_URL="%f" BUILD_ID="%R" OPENWRT_BOARD="%S" OPENWRT_ARCH="%A" @@ -16,3 +17,4 @@ OPENWRT_DEVICE_MANUFACTURER_URL="%m" OPENWRT_DEVICE_PRODUCT="%P" OPENWRT_DEVICE_REVISION="%h" OPENWRT_RELEASE="%D %V %C" +OPENWRT_BUILD_DATE="%B" diff --git a/package/base-files/luci2/bin/config_generate b/package/base-files/luci/bin/config_generate similarity index 87% rename from package/base-files/luci2/bin/config_generate rename to package/base-files/luci/bin/config_generate index a6baf7960..7e0dc62b9 100755 --- a/package/base-files/luci2/bin/config_generate +++ b/package/base-files/luci/bin/config_generate @@ -40,7 +40,7 @@ generate_static_network() { uci -q batch <<-EOF delete network.loopback set network.loopback='interface' - set network.loopback.device='lo' + set network.loopback.ifname='lo' set network.loopback.proto='static' set network.loopback.ipaddr='127.0.0.1' set network.loopback.netmask='255.0.0.0' @@ -91,73 +91,58 @@ generate_static_network() { addr_offset=2 generate_network() { - local ports device macaddr protocol type ipaddr netmask vlan + local ports ifname macaddr protocol type ipaddr netmask vlan local bridge=$2 json_select network json_select "$1" - json_get_vars device macaddr metric protocol ipaddr netmask vlan json_get_values ports ports + json_get_vars ifname macaddr protocol ipaddr netmask vlan json_select .. json_select .. - [ -n "$device" -o -n "$ports" ] || return + [ -n "$ifname" -o -n "$ports" ] || return # Force bridge for "lan" as it may have other devices (e.g. wireless) # bridged [ "$1" = "lan" -a -z "$ports" ] && { - ports="$device" + ports="$ifname" } - [ -n "$ports" -a -z "$bridge" ] && { - uci -q batch <<-EOF - add network device - set network.@device[-1].name='br-$1' - set network.@device[-1].type='bridge' - EOF - for port in $ports; do uci add_list network.@device[-1].ports="$port"; done - [ -n "$macaddr" ] && { - for port in $ports; do - uci -q batch <<-EOF - add network device - set network.@device[-1].name='$port' - set network.@device[-1].macaddr='$macaddr' - EOF - done - } - device=br-$1 - type= - macaddr="" + [ -n "$ports" ] && { + type="bridge" + ifname="$ports" } [ -n "$bridge" ] && { - [ -z "$ports" ] && ports="$device" if [ -z "$vlan" ]; then bridge_vlan_id=$((bridge_vlan_id + 1)) vlan=$bridge_vlan_id fi - generate_bridge_vlan $1 $bridge "$ports" $vlan - device=$bridge.$vlan + generate_bridge_vlan $1 $bridge "$ifname" $vlan + ifname=$bridge.$vlan type="" } - if [ -n "$macaddr" ]; then - uci -q batch <<-EOF - add network device - set network.@device[-1].name='$device' - set network.@device[-1].macaddr='$macaddr' - EOF - fi - uci -q batch <<-EOF delete network.$1 set network.$1='interface' set network.$1.type='$type' - set network.$1.device='$device' - set network.$1.metric='$metric' + set network.$1.ifname='$ifname' set network.$1.proto='none' EOF + if [ -n "$macaddr" ]; then + for name in $ifname; do + uci -q batch <<-EOF + delete network.$1_${name/./_}_dev + set network.$1_${name/./_}_dev='device' + set network.$1_${name/./_}_dev.name='$name' + set network.$1_${name/./_}_dev.macaddr='$macaddr' + EOF + done + fi + case "$protocol" in static) local ipad @@ -178,14 +163,14 @@ generate_network() { dhcp) # fixup IPv6 slave interface if parent is a bridge - [ "$type" = "bridge" ] && device="br-$1" + [ "$type" = "bridge" ] && ifname="br-$1" uci set network.$1.proto='dhcp' [ -e /proc/sys/net/ipv6 ] && { uci -q batch <<-EOF delete network.${1}6 set network.${1}6='interface' - set network.${1}6.device='$device' + set network.${1}6.ifname='$ifname' set network.${1}6.proto='dhcpv6' EOF } @@ -202,7 +187,7 @@ generate_network() { set network.$1.ipv6='1' delete network.${1}6 set network.${1}6='interface' - set network.${1}6.device='@${1}' + set network.${1}6.ifname='@${1}' set network.${1}6.proto='dhcpv6' EOF } @@ -314,17 +299,17 @@ generate_static_system() { set system.@system[-1].hostname='LEDE' set system.@system[-1].timezone='UTC' set system.@system[-1].ttylogin='0' - set system.@system[-1].log_size='64' + set system.@system[-1].log_size='128' set system.@system[-1].urandom_seed='0' delete system.ntp set system.ntp='timeserver' set system.ntp.enabled='1' - set system.ntp.enable_server='0' - add_list system.ntp.server='0.openwrt.pool.ntp.org' - add_list system.ntp.server='1.openwrt.pool.ntp.org' - add_list system.ntp.server='2.openwrt.pool.ntp.org' - add_list system.ntp.server='3.openwrt.pool.ntp.org' + set system.ntp.enable_server='1' + add_list system.ntp.server='time.apple.com' + add_list system.ntp.server='time.google.com' + add_list system.ntp.server='time.windows.com' + add_list system.ntp.server='time.cloudflare.com' EOF if json_is_a system object; then diff --git a/package/base-files/luci2/lib/functions/uci-defaults.sh b/package/base-files/luci/lib/functions/uci-defaults.sh similarity index 96% rename from package/base-files/luci2/lib/functions/uci-defaults.sh rename to package/base-files/luci/lib/functions/uci-defaults.sh index 6f395ec24..55e1fde16 100644 --- a/package/base-files/luci2/lib/functions/uci-defaults.sh +++ b/package/base-files/luci/lib/functions/uci-defaults.sh @@ -39,7 +39,7 @@ ucidef_set_interface() { [ -n "$opt" -a -n "$val" ] || break - [ "$opt" = "device" -a "$val" != "${val/ //}" ] && { + [ "$opt" = "ifname" -a "$val" != "${val/ //}" ] && { json_select_array "ports" for e in $val; do json_add_string "" "$e"; done json_close_array @@ -79,11 +79,11 @@ ucidef_set_compat_version() { } ucidef_set_interface_lan() { - ucidef_set_interface "lan" device "$1" protocol "${2:-static}" + ucidef_set_interface "lan" ifname "$1" protocol "${2:-static}" } ucidef_set_interface_wan() { - ucidef_set_interface "wan" device "$1" protocol "${2:-dhcp}" + ucidef_set_interface "wan" ifname "$1" protocol "${2:-dhcp}" } ucidef_set_interfaces_lan_wan() { @@ -107,21 +107,13 @@ ucidef_set_bridge_mac() { } ucidef_set_network_device_mac() { - json_select_object "network_device" + json_select_object "network-device" json_select_object "${1}" json_add_string macaddr "${2}" json_select .. json_select .. } -ucidef_set_network_device_path() { - json_select_object "network_device" - json_select_object "$1" - json_add_string path "$2" - json_select .. - json_select .. -} - _ucidef_add_switch_port() { # inherited: $num $device $need_tag $want_untag $role $index $prev_role # inherited: $n_cpu $n_ports $n_vlan $cpu0 $cpu1 $cpu2 $cpu3 $cpu4 $cpu5 @@ -209,14 +201,14 @@ _ucidef_finish_switch_roles() { json_select_object "$role" # attach previous interfaces (for multi-switch devices) - json_get_var devices device + json_get_var devices ifname if ! list_contains devices "$device"; then devices="${devices:+$devices }$device" fi json_select .. json_select .. - ucidef_set_interface "$role" device "$devices" + ucidef_set_interface "$role" ifname "$devices" done } diff --git a/package/base-files/luci2/lib/preinit/10_indicate_preinit b/package/base-files/luci/lib/preinit/10_indicate_preinit similarity index 69% rename from package/base-files/luci2/lib/preinit/10_indicate_preinit rename to package/base-files/luci/lib/preinit/10_indicate_preinit index a8f7758c8..1996ca5ee 100644 --- a/package/base-files/luci2/lib/preinit/10_indicate_preinit +++ b/package/base-files/luci/lib/preinit/10_indicate_preinit @@ -63,20 +63,6 @@ preinit_config_switch() { json_select .. } -preinit_config_port() { - local original - - local netdev="$1" - local path="$2" - - [ -d "/sys/devices/$path/net" ] || return - original="$(ls "/sys/devices/$path/net" | head -1)" - - [ "$netdev" = "$original" ] && return - - ip link set "$original" name "$netdev" -} - preinit_config_board() { /bin/board_detect /tmp/board.json @@ -87,49 +73,16 @@ preinit_config_board() { json_init json_load "$(cat /tmp/board.json)" - # Find the current highest eth* - max_eth=$(grep -o '^ *eth[0-9]*:' /proc/net/dev | tr -dc '[0-9]\n' | sort -n | tail -1) - # Find and move netdevs using eth*s we are configuring - json_get_keys keys "network_device" - for netdev in $keys; do - json_select "network_device" - json_select "$netdev" - json_get_vars path path - if [ -n "$path" -a -h "/sys/class/net/$netdev" ]; then - ip link set "$netdev" down - ip link set "$netdev" name eth$((++max_eth)) - fi - json_select .. - json_select .. - done - - # Move interfaces by path to their netdev name - json_get_keys keys "network_device" - for netdev in $keys; do - json_select "network_device" - json_select "$netdev" - json_get_vars path path - [ -n "$path" ] && preinit_config_port "$netdev" "$path" - json_select .. - json_select .. - done - json_select network json_select "lan" - json_get_vars device - json_get_values ports ports + json_get_vars ifname json_select .. json_select .. - [ -n "$device" -o -n "$ports" ] || return - - # swconfig uses $device and DSA uses ports - [ -z "$ports" ] && { - ports="$device" - } + [ -n "$ifname" ] || return # only use the first one - ifname=${ports%% *} + ifname=${ifname%% *} if [ -x /sbin/swconfig ]; then # configure the switch, if present