b.liu | e958203 | 2025-04-17 19:18:16 +0800 | [diff] [blame] | 1 | # Copyright (C) 2006-2013 OpenWrt.org |
| 2 | |
| 3 | . /lib/functions.sh |
| 4 | . /usr/share/libubox/jshn.sh |
| 5 | |
| 6 | get_mac_binary() { |
| 7 | local path="$1" |
| 8 | local offset="$2" |
| 9 | |
| 10 | if ! [ -e "$path" ]; then |
| 11 | echo "get_mac_binary: file $path not found!" >&2 |
| 12 | return |
| 13 | fi |
| 14 | |
| 15 | hexdump -v -n 6 -s $offset -e '5/1 "%02x:" 1/1 "%02x"' $path 2>/dev/null |
| 16 | } |
| 17 | |
| 18 | get_mac_label_dt() { |
| 19 | local basepath="/proc/device-tree" |
| 20 | local macdevice="$(cat "$basepath/aliases/label-mac-device" 2>/dev/null)" |
| 21 | local macaddr |
| 22 | |
| 23 | [ -n "$macdevice" ] || return |
| 24 | |
| 25 | macaddr=$(get_mac_binary "$basepath/$macdevice/mac-address" 0 2>/dev/null) |
| 26 | [ -n "$macaddr" ] || macaddr=$(get_mac_binary "$basepath/$macdevice/local-mac-address" 0 2>/dev/null) |
| 27 | |
| 28 | echo $macaddr |
| 29 | } |
| 30 | |
| 31 | get_mac_label_json() { |
| 32 | local cfg="/etc/board.json" |
| 33 | local macaddr |
| 34 | |
| 35 | [ -s "$cfg" ] || return |
| 36 | |
| 37 | json_init |
| 38 | json_load "$(cat $cfg)" |
| 39 | if json_is_a system object; then |
| 40 | json_select system |
| 41 | json_get_var macaddr label_macaddr |
| 42 | json_select .. |
| 43 | fi |
| 44 | |
| 45 | echo $macaddr |
| 46 | } |
| 47 | |
| 48 | get_mac_label() { |
| 49 | local macaddr=$(get_mac_label_dt) |
| 50 | |
| 51 | [ -n "$macaddr" ] || macaddr=$(get_mac_label_json) |
| 52 | |
| 53 | echo $macaddr |
| 54 | } |
| 55 | |
| 56 | find_mtd_chardev() { |
| 57 | local INDEX=$(find_mtd_index "$1") |
| 58 | local PREFIX=/dev/mtd |
| 59 | |
| 60 | [ -d /dev/mtd ] && PREFIX=/dev/mtd/ |
| 61 | echo "${INDEX:+$PREFIX$INDEX}" |
| 62 | } |
| 63 | |
| 64 | get_mac_ascii() { |
| 65 | local part="$1" |
| 66 | local key="$2" |
| 67 | local mac_dirty |
| 68 | |
| 69 | mac_dirty=$(strings "$part" | tr -d ' \t' | sed -n 's/^'"$key"'=//p' | head -n 1) |
| 70 | |
| 71 | # "canonicalize" mac |
| 72 | [ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty" |
| 73 | } |
| 74 | |
| 75 | mtd_get_mac_ascii() { |
| 76 | local mtdname="$1" |
| 77 | local key="$2" |
| 78 | local part |
| 79 | |
| 80 | part=$(find_mtd_part "$mtdname") |
| 81 | if [ -z "$part" ]; then |
| 82 | echo "mtd_get_mac_ascii: partition $mtdname not found!" >&2 |
| 83 | return |
| 84 | fi |
| 85 | |
| 86 | get_mac_ascii "$part" "$key" |
| 87 | } |
| 88 | |
| 89 | mtd_get_mac_encrypted_arcadyan() { |
| 90 | local iv="00000000000000000000000000000000" |
| 91 | local key="2A4B303D7644395C3B2B7053553C5200" |
| 92 | local mac_dirty |
| 93 | local mtdname="$1" |
| 94 | local part |
| 95 | local size |
| 96 | |
| 97 | part=$(find_mtd_part "$mtdname") |
| 98 | if [ -z "$part" ]; then |
| 99 | echo "mtd_get_mac_encrypted_arcadyan: partition $mtdname not found!" >&2 |
| 100 | return |
| 101 | fi |
| 102 | |
| 103 | # Config decryption and getting mac. Trying uencrypt and openssl utils. |
| 104 | size=$((0x$(dd if=$part skip=9 bs=1 count=4 2>/dev/null | hexdump -v -e '1/4 "%08x"'))) |
| 105 | if [[ -f "/usr/bin/uencrypt" ]]; then |
| 106 | mac_dirty=$(dd if=$part bs=1 count=$size skip=$((0x100)) 2>/dev/null | \ |
| 107 | uencrypt -d -n -k $key -i $iv | grep mac | cut -c 5-) |
| 108 | elif [[ -f "/usr/bin/openssl" ]]; then |
| 109 | mac_dirty=$(dd if=$part bs=1 count=$size skip=$((0x100)) 2>/dev/null | \ |
| 110 | openssl aes-128-cbc -d -nopad -K $key -iv $iv | grep mac | cut -c 5-) |
| 111 | else |
| 112 | echo "mtd_get_mac_encrypted_arcadyan: Neither uencrypt nor openssl was found!" >&2 |
| 113 | return |
| 114 | fi |
| 115 | |
| 116 | # "canonicalize" mac |
| 117 | [ -n "$mac_dirty" ] && macaddr_canonicalize "$mac_dirty" |
| 118 | } |
| 119 | |
| 120 | mtd_get_mac_encrypted_deco() { |
| 121 | local mtdname="$1" |
| 122 | |
| 123 | if ! [ -e "$mtdname" ]; then |
| 124 | echo "mtd_get_mac_encrypted_deco: file $mtdname not found!" >&2 |
| 125 | return |
| 126 | fi |
| 127 | |
| 128 | tplink_key="3336303032384339" |
| 129 | |
| 130 | key=$(dd if=$mtdname bs=1 skip=16 count=8 2>/dev/null | \ |
| 131 | uencrypt -n -d -k $tplink_key -c des-ecb | hexdump -v -n 8 -e '1/1 "%02x"') |
| 132 | |
| 133 | macaddr=$(dd if=$mtdname bs=1 skip=32 count=8 2>/dev/null | \ |
| 134 | uencrypt -n -d -k $key -c des-ecb | hexdump -v -n 6 -e '5/1 "%02x:" 1/1 "%02x"') |
| 135 | |
| 136 | echo $macaddr |
| 137 | } |
| 138 | |
| 139 | mtd_get_mac_uci_config_ubi() { |
| 140 | local volumename="$1" |
| 141 | |
| 142 | . /lib/upgrade/nand.sh |
| 143 | |
| 144 | local ubidev=$(nand_attach_ubi $CI_UBIPART) |
| 145 | local part=$(nand_find_volume $ubidev $volumename) |
| 146 | |
| 147 | cat "/dev/$part" | sed -n 's/^\s*option macaddr\s*'"'"'\?\([0-9A-F:]\+\)'"'"'\?/\1/Ip' |
| 148 | } |
| 149 | |
| 150 | mtd_get_mac_text() { |
| 151 | local mtdname="$1" |
| 152 | local offset=$((${2:-0})) |
| 153 | local length="${3:-17}" |
| 154 | local part |
| 155 | |
| 156 | part=$(find_mtd_part "$mtdname") |
| 157 | if [ -z "$part" ]; then |
| 158 | echo "mtd_get_mac_text: partition $mtdname not found!" >&2 |
| 159 | return |
| 160 | fi |
| 161 | |
| 162 | [ $((offset + length)) -le $(mtd_get_part_size "$mtdname") ] || return |
| 163 | |
| 164 | macaddr_canonicalize $(dd bs=1 if="$part" skip="$offset" count="$length" 2>/dev/null) |
| 165 | } |
| 166 | |
| 167 | mtd_get_mac_binary() { |
| 168 | local mtdname="$1" |
| 169 | local offset="$2" |
| 170 | local part |
| 171 | |
| 172 | part=$(find_mtd_part "$mtdname") |
| 173 | get_mac_binary "$part" "$offset" |
| 174 | } |
| 175 | |
| 176 | mtd_get_mac_binary_ubi() { |
| 177 | local mtdname="$1" |
| 178 | local offset="$2" |
| 179 | |
| 180 | . /lib/upgrade/nand.sh |
| 181 | |
| 182 | local ubidev=$(nand_find_ubi $CI_UBIPART) |
| 183 | local part=$(nand_find_volume $ubidev $1) |
| 184 | |
| 185 | get_mac_binary "/dev/$part" "$offset" |
| 186 | } |
| 187 | |
| 188 | mtd_get_part_size() { |
| 189 | local part_name=$1 |
| 190 | local first dev size erasesize name |
| 191 | while read dev size erasesize name; do |
| 192 | name=${name#'"'}; name=${name%'"'} |
| 193 | if [ "$name" = "$part_name" ]; then |
| 194 | echo $((0x$size)) |
| 195 | break |
| 196 | fi |
| 197 | done < /proc/mtd |
| 198 | } |
| 199 | |
| 200 | mmc_get_mac_ascii() { |
| 201 | local part_name="$1" |
| 202 | local key="$2" |
| 203 | local part |
| 204 | |
| 205 | part=$(find_mmc_part "$part_name") |
| 206 | if [ -z "$part" ]; then |
| 207 | echo "mmc_get_mac_ascii: partition $part_name not found!" >&2 |
| 208 | return |
| 209 | fi |
| 210 | |
| 211 | get_mac_ascii "$part" "$key" |
| 212 | } |
| 213 | |
| 214 | mmc_get_mac_binary() { |
| 215 | local part_name="$1" |
| 216 | local offset="$2" |
| 217 | local part |
| 218 | |
| 219 | part=$(find_mmc_part "$part_name") |
| 220 | get_mac_binary "$part" "$offset" |
| 221 | } |
| 222 | |
| 223 | macaddr_add() { |
| 224 | local mac=$1 |
| 225 | local val=$2 |
| 226 | local oui=${mac%:*:*:*} |
| 227 | local nic=${mac#*:*:*:} |
| 228 | |
| 229 | nic=$(printf "%06x" $((0x${nic//:/} + val & 0xffffff)) | sed 's/^\(.\{2\}\)\(.\{2\}\)\(.\{2\}\)/\1:\2:\3/') |
| 230 | echo $oui:$nic |
| 231 | } |
| 232 | |
| 233 | macaddr_generate_from_mmc_cid() { |
| 234 | local mmc_dev=$1 |
| 235 | |
| 236 | local sd_hash=$(sha256sum /sys/class/block/$mmc_dev/device/cid) |
| 237 | local mac_base=$(macaddr_canonicalize "$(echo "${sd_hash}" | dd bs=1 count=12 2>/dev/null)") |
| 238 | echo "$(macaddr_unsetbit_mc "$(macaddr_setbit_la "${mac_base}")")" |
| 239 | } |
| 240 | |
| 241 | macaddr_geteui() { |
| 242 | local mac=$1 |
| 243 | local sep=$2 |
| 244 | |
| 245 | echo ${mac:9:2}$sep${mac:12:2}$sep${mac:15:2} |
| 246 | } |
| 247 | |
| 248 | macaddr_setbit() { |
| 249 | local mac=$1 |
| 250 | local bit=${2:-0} |
| 251 | |
| 252 | [ $bit -gt 0 -a $bit -le 48 ] || return |
| 253 | |
| 254 | printf "%012x" $(( 0x${mac//:/} | 2**(48-bit) )) | sed -e 's/\(.\{2\}\)/\1:/g' -e 's/:$//' |
| 255 | } |
| 256 | |
| 257 | macaddr_unsetbit() { |
| 258 | local mac=$1 |
| 259 | local bit=${2:-0} |
| 260 | |
| 261 | [ $bit -gt 0 -a $bit -le 48 ] || return |
| 262 | |
| 263 | printf "%012x" $(( 0x${mac//:/} & ~(2**(48-bit)) )) | sed -e 's/\(.\{2\}\)/\1:/g' -e 's/:$//' |
| 264 | } |
| 265 | |
| 266 | macaddr_setbit_la() { |
| 267 | macaddr_setbit $1 7 |
| 268 | } |
| 269 | |
| 270 | macaddr_unsetbit_mc() { |
| 271 | local mac=$1 |
| 272 | |
| 273 | printf "%02x:%s" $((0x${mac%%:*} & ~0x01)) ${mac#*:} |
| 274 | } |
| 275 | |
| 276 | macaddr_random() { |
| 277 | local randsrc=$(get_mac_binary /dev/urandom 0) |
| 278 | |
| 279 | echo "$(macaddr_unsetbit_mc "$(macaddr_setbit_la "${randsrc}")")" |
| 280 | } |
| 281 | |
| 282 | macaddr_canonicalize() { |
| 283 | local mac="$1" |
| 284 | local canon="" |
| 285 | |
| 286 | mac=$(echo -n $mac | tr -d \") |
| 287 | [ ${#mac} -gt 17 ] && return |
| 288 | [ -n "${mac//[a-fA-F0-9\.: -]/}" ] && return |
| 289 | |
| 290 | for octet in ${mac//[\.:-]/ }; do |
| 291 | case "${#octet}" in |
| 292 | 1) |
| 293 | octet="0${octet}" |
| 294 | ;; |
| 295 | 2) |
| 296 | ;; |
| 297 | 4) |
| 298 | octet="${octet:0:2} ${octet:2:2}" |
| 299 | ;; |
| 300 | 12) |
| 301 | octet="${octet:0:2} ${octet:2:2} ${octet:4:2} ${octet:6:2} ${octet:8:2} ${octet:10:2}" |
| 302 | ;; |
| 303 | *) |
| 304 | return |
| 305 | ;; |
| 306 | esac |
| 307 | canon=${canon}${canon:+ }${octet} |
| 308 | done |
| 309 | |
| 310 | [ ${#canon} -ne 17 ] && return |
| 311 | |
| 312 | printf "%02x:%02x:%02x:%02x:%02x:%02x" 0x${canon// / 0x} 2>/dev/null |
| 313 | } |
| 314 | |
| 315 | dt_is_enabled() { |
| 316 | grep -q okay "/proc/device-tree/$1/status" |
| 317 | } |