0

When I execute the command ip address show my server shows hundreds of IPv6 that I have assigned to it. It works great, however the leading and trailing zeros are omitted from the IP addresses, and are shown like:

3600:3c00:e000:92b::5/64 

I need the IP to get shown in the complete form like:

3600:3c00:e000:092b:0000:0005/64

because later I will match the result of ip address show into a regex to check for addresses from a list and all of them are in the "complete form".

Do you have any idea how I can fix this?

3
  • Not possible to mark duplicate as it's a different site, but stackoverflow.com/questions/14697403/… should answer it.
    – vidarlo
    Commented Jan 27 at 20:04
  • RFC 5952, which specifies compressed text IPv6 addressing as the canonical format for text representation says, "This document defines a canonical textual representation format. It does not define a format for internal storage, such as within an application or database. It is expected that the canonical format will be followed by humans and systems when representing IPv6 addresses as text, but all implementations must accept and be able to handle any legitimate RFC 4291 format." The OS is following the RFC.
    – Ron Maupin
    Commented Jan 27 at 20:54
  • 1
    "I will match the result of ip address show into a regex to check for IPs from a list and all of them are in the 'complete form.'" You can use a regular expression that matches any of the RFC 4291 IPv6 text representations. For example. I made this IPv6 regular expression.
    – Ron Maupin
    Commented Jan 27 at 21:06

1 Answer 1

2

the following bash script will print IPv6 in expanded and in /proc/net/tcp6 format too (you can remove the last echo if you don't need it):

#!/bin/bash

# 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)
}

# print ipv6 in linux /proc/net/tcp6 format
ipv6ToNetTcp6() {
  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

  word1="0x$1"
  word2="0x$2"
  word3="0x$3"
  word4="0x$4"
  word5="0x$5"
  word6="0x$6"
  word7="0x$7"
  word8="0x$8"
  printf "%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n" \
    $((word2 & 0xFF)) \
    $((word2 >> 8)) \
    $((word1 & 0xFF)) \
    $((word1 >> 8)) \
    $((word4 & 0xFF)) \
    $((word4 >> 8)) \
    $((word3 & 0xFF)) \
    $((word3 >> 8)) \
    $((word6 & 0xFF)) \
    $((word6 >> 8)) \
    $((word5 & 0xFF)) \
    $((word5 >> 8)) \
    $((word8 & 0xFF)) \
    $((word8 >> 8)) \
    $((word7 & 0xFF)) \
    $((word7 >> 8))
}

result=$(expand_ipv6 $1)
echo $result
result2=$(ipv6ToNetTcp6 $1)
echo $result2

exit 0

E.g., after giving it execution permission:

# ./fullip6 "3600:3c00:e000:92b::5/64"
3600:3c00:e000:092b:0000:0000:0000:0005
003C00362B0900E00000000005000000

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .