我想根据给定的 IPv6 地址更新 djbdns (dbndns) 配置文件,例如2a01:488:66:1000:523:f116:0:1
或::1
.
dbndns 需要扩展的 IPv6 地址,2a010488006610000523f11600000001
例如2a01:488:66:1000:523:f116:0:1
.
扩展这种 IPv6 地址的最简单方法是什么?
使用sipcalc
可能会做到这一点。它提供了比您需要的更多的信息,但有点grep
并且cut
可以解决这个问题:-)
$ EXPANDED=`sipcalc 2001::1 | fgrep Expanded | cut -d '-' -f 2`
$ echo $EXPAND
2001:0000:0000:0000:0000:0000:0000:0001
作为参考,这是完整的输出sipcalc
:
$ sipcalc 2001::1
-[ipv6 : 2001::1] - 0
[IPV6 INFO]
Expanded Address - 2001:0000:0000:0000:0000:0000:0000:0001
Compressed address - 2001::1
Subnet prefix (masked) - 2001:0:0:0:0:0:0:1/128
Address ID (masked) - 0:0:0:0:0:0:0:0/128
Prefix address - ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
Prefix length - 128
Address type - Aggregatable Global Unicast Addresses
Network range - 2001:0000:0000:0000:0000:0000:0000:0001 -
2001:0000:0000:0000:0000:0000:0000:0001
我最近想要一个无依赖的解决方案,它可以跨 shell 移植并在诸如 openwrt 之类的平台上工作。我想出了以下片段:
# helper to convert hex to dec (portable version)
hex2dec(){
[ "$1" != "" ] && printf "%d" "$(( 0x$1 ))"
}
# expand an ipv6 address
expand_ipv6() {
ip=$1
# prepend 0 if we start with :
echo $ip | grep -qs "^:" && ip="0${ip}"
# expand ::
if echo $ip | grep -qs "::"; then
colons=$(echo $ip | sed 's/[^:]//g')
missing=$(echo ":::::::::" | sed "s/$colons//")
expanded=$(echo $missing | sed 's/:/:0/g')
ip=$(echo $ip | sed "s/::/$expanded/")
fi
blocks=$(echo $ip | grep -o "[0-9a-f]\+")
set $blocks
printf "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x\n" \
$(hex2dec $1) \
$(hex2dec $2) \
$(hex2dec $3) \
$(hex2dec $4) \
$(hex2dec $5) \
$(hex2dec $6) \
$(hex2dec $7) \
$(hex2dec $8)
}
我也有这个功能来压缩
# returns a compressed ipv6 address under the form recommended by RFC5952
compress_ipv6() {
ip=$1
blocks=$(echo $ip | grep -o "[0-9a-f]\+")
set $blocks
# compress leading zeros
ip=$(printf "%x:%x:%x:%x:%x:%x:%x:%x\n" \
$(hex2dec $1) \
$(hex2dec $2) \
$(hex2dec $3) \
$(hex2dec $4) \
$(hex2dec $5) \
$(hex2dec $6) \
$(hex2dec $7) \
$(hex2dec $8)
)
# prepend : for easier matching
ip=:$ip
# :: must compress the longest chain
for pattern in :0:0:0:0:0:0:0:0 \
:0:0:0:0:0:0:0 \
:0:0:0:0:0:0 \
:0:0:0:0:0 \
:0:0:0:0 \
:0:0; do
if echo $ip | grep -qs $pattern; then
ip=$(echo $ip | sed "s/$pattern/::/")
# if the substitution occured before the end, we have :::
ip=$(echo $ip | sed 's/:::/::/')
break # only one substitution
fi
done
# remove prepending : if necessary
echo $ip | grep -qs "^:[^:]" && ip=$(echo $ip | sed 's/://')
echo $ip
}
您可以将它们结合起来测试给定的输入是否是 ipv6
# a valid ipv6 is either the expanded form or the compressed one
is_ipv6(){
expanded="$(expand_ipv6 $1)"
[ "$1" = "$expanded" ] && return 0
compressed="$(compress_ipv6 $expanded)"
[ "$1" = "$compressed" ] && return 0
return 1
}
我希望这有帮助!这些片段取自https://github.com/chmduquesne/wg-ip。如果您发现任何错误,请贡献!
你可以吗?
kent$ echo "2a01:488:66:1000:523:f116:0:1"|awk -F: '{for(i=1;i<=NF;i++)x=x""sprintf ("%4s", $i);gsub(/ /,"0",x);print x}'
2a010488006610000523f11600000001
__rfc5952_expand () {
read addr mask < <(IFS=/; echo $1)
quads=$(grep -oE "[a-fA-F0-9]{1,4}" <<< ${addr/\/*} | wc -l)
#[ "${addr:${#addr}-1}" == ":" ] && { addr="${addr}0000"; (( quads++ )); }
grep -qs ":$" <<< $addr && { addr="${addr}0000"; (( quads++ )); }
grep -qs "^:" <<< $addr && { addr="0000${addr}"; (( quads++ )); }
[ $quads -lt 8 ] && addr=${addr/::/:$(for (( i=1; i<=$(( 8 - quads )) ; i++ )); do printf "0000:"; done)}
#addr=$(
#for quad in $(IFS=:; echo ${addr}); do
# [ "${#quad}" -lt 4 ] && for (( i=${#quad}; i<4 ; i++ )); do quad=0${quad}; done
# printf "${delim}${quad}"; delim=":";
# Or so if you need result without colon, as asked in first post
# printf "${quad}";
#done)
addr=$(for quad in $(IFS=:; echo ${addr}); do printf "${delim}%04x" "0x${quad}"; delim=":"; done)
#addr=$(for quad in $(IFS=:; echo ${addr}); do printf "%04x" "0x${quad}"; done)
[ ! -z $mask ] && echo $addr/$mask || echo $addr
}
for ip in 2a01:4f8:211:9e::/64 ::1/128; do __rfc5952_expand $ip; done
2a01:04f8:0211:009e:0000:0000:0000:0000/64
0000:0000:0000:0000:0000:0000:0000:0001/128
__rfc5952_compact () {
read addr mask < <(IFS=/; echo $1)
addr=$(for quad in $(IFS=:; echo ${addr}); do printf "${delim}%x" "0x${quad}"; delim=":"; done)
for zeros in $(grep -oE "((^|:)0)+:?" <<< $addr | sort -r | head -1); do addr=${addr/$zeros/::}; done
[ ! -z $mask ] && echo $addr/$mask || echo $addr
}
for ip in 2a01:04f8:0211:009e:00:0001:0000:0000/64 0000:0000:0000:0000:0000:0000:0000:0001/128; do __rfc5952_compact $ip; done
2a01:4f8:211:9e:0:1::/64
::1/128