How to read an IP address backwards?

If we have this string (IP address): 192.168.1.1

How can I derive the (DNS reverse record form) from this string, so it will be shown like 1.1.168.192.in-addr.arpa using a shell script?

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

Just for curiosity value… using tac from GNU coreutils: given a variable ip in the form 192.168.1.1 then

$(printf %s "$ip." | tac -s.)in-addr.arpa

i.e.

$ ip=192.168.1.1
$ rr=$(printf %s "$ip." | tac -s.)in-addr.arpa
$ echo "$rr"
1.1.168.192.in-addr.arpa

Method 2

You can do it with AWK. There are nicer ways to do it, but this is the simplest, I think.

echo '192.168.1.1' | awk 'BEGIN{FS="."}{print $4"."$3"."$2"."$1".in-addr.arpa"}'

This will reverse the order of the IP address.

Just to save a few keystrokes, as Mikel suggested, we can further shorten the upper statement:

echo '192.168.1.1' | awk -F . '{print $4"."$3"."$2"."$1".in-addr.arpa"}'

OR

echo '192.168.1.1' | awk -F. '{print $4"."$3"."$2"."$1".in-addr.arpa"}'

OR

echo '192.168.1.1' | awk -F. -vOFS=. '{print $4,$3,$2,$1,"in-addr.arpa"}'

AWK is pretty flexible. 🙂

Method 3

If you want to use only shell (zsh, ksh93, bash), here’s another way:

IFS=. read w x y z <<<'192.168.1.1'
printf '%d.%d.%d.%d.in-addr.arpa.' "$z" "$y" "$x" "$w"

Or in plain old shell:

echo '192.168.1.1' | { IFS=. read w x y z; echo "$z.$y.$w.$x.in-addr.arpa."; }

Method 4

Easily with Perl, thusly:

$ echo 192.168.1.1|perl -nle 'print join ".",reverse(split /./,$_)'
1.1.168.192

Method 5

To round it out, Ruby:

ruby -r ipaddr -e 'puts IPAddr.new(ARGV.first).reverse' 192.168.1.1

Which also supports IPv6

2607:F8B0:4000:080A:0000:0000:0000:2000
=> 0.0.0.2.0.0.0.0.0.0.0.0.0.0.0.0.a.0.8.0.0.0.0.4.0.b.8.f.7.0.6.2.ip6.arpa

Method 6

Through GNU sed,

sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/4.3.2.1.in-addr.arpa/g' file

It reverses any IPv4-address format.

Example:

$ echo '192.168.1.1' | sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/4.3.2.1.in-addr.arpa/g'
1.1.168.192.in-addr.arpa

$ echo '192.1.1.1' | sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/4.3.2.1.in-addr.arpa/g'
1.1.1.192.in-addr.arpa

$ echo '1.1.1.1' | sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/4.3.2.1.in-addr.arpa/g'
1.1.1.1.in-addr.arpa

$ sed -r 's/^([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3}).([0-9]{1,3})$/4.3.2.1.in-addr.arpa/g' <<< '192.168.189.23'
23.189.168.192.in-addr.arpa

Method 7

With zsh:

$ ip=192.168.1.1
$ echo ${(j:.:)${(s:.:Oa)ip}}.in-addr.arpa
1.1.168.192.in-addr.arpa

Those are variable expansion flags:

  • s:.:: split on .
  • Oa: reverse order the array
  • j:.:: join on .

Method 8

Using Python’s standard library:

>>> ipaddress.ip_address('192.168.1.1').reverse_pointer
'1.1.168.192.in-addr.arpa'

Method 9

Another possibility is to use the “dig” command line tool with the “-x” switch.

It actually does a request on the PTR entry, but if you filter on “PTR” it will show you one commented line (the request) and maybe some replies.

Using “dig” can be handy for a quick writing of the PTR name, without having to write a small script. Particularly if you need it interactively (to cut and paste the result).
It works on IPv6 too.

Method 10

If you want it working with IPv6 as well, you can use dig -x.

For example:

$ dig -x 194.68.208.240 | egrep '^;.*PTR$' | cut -c 2- | awk '{print $1}'
240.208.68.194.in-addr.arpa.

$ dig -x 2001:db8:dc61:2a61::1 | egrep '^;.*PTR$' | cut -c 2- | awk '{print $1}'
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.6.a.2.1.6.c.d.8.b.d.0.1.0.0.2.ip6.arpa.

Method 11

In Python

 a = "192.168.1.122"
 import re
 m = re.search(r'(d+).(d+).(d+).(d+)',a)
 ip = m.group(4),m.group(3),m.group(2),m.group(1)
 '.'.join(ip) + ".in-addr.arpa"
 '122.1.168.192.in-addr.arpa'

Method 12

IFS=. ; set -- ${0+192.168.1.2}
printf %b. $4 $3 $2 $1 in-addr.arpa\c

IFS=. ; printf %s\n 
    in-addr.arpa ${0+192.168.1.2} |    
sed '1!G;$s/n/./gp;h;d'

IFS=. ; printf '[%b.] ' 
    ${0+192.168.1.2.]PPPPP\c} |dc
echo in-addr.arpa

Method 13

$ while read ip
while> do
while> n=( $(echo $ip) ) && echo "${n[4]}"'.'"${n[3]}"'.'"${n[2]}"'.'"${n[1]}"'.'"in-addr.arpa"
while> done
192.168.1.2
2.1.168.192.in-addr.arpa

This way you can type in an address and hit return for your result.

Method 14

Assuming a var contains the ip: ip=192.168.2.1. If the value needs to be given to a new variable, just enclose any solution inside $() and assign that to the var rr=$(...).

Some solutions are possible:

Simplest : printf 'arpa.in-addr.%s.' "$ip" | tac -s.
Most shells: IFS=. eval 'set -- $ip'; echo "$4.$3.$2.$1.in-addr.arpa"
Some shells : IFS=. read d c b a <<<"$ip"; printf %s "$a.$b.$c.$d.in-addr.arpa."
: echo "$ip" | awk -F. '{OFS=FS;print $4,$3,$2,$1,"in-addr.arpa"}'
: echo "$ip" | sed -E 's/([^.]+).([^.]+).([^.]+).([^.]+)$/4.3.2.1.in-addr.arpa./'
: echo "arpa.in-addr.$ip" | sed 'y/./n/' | sed 'G;$s/n/./gp;h;d'
: echo "$ip" | perl -F\. -lane '$,=".";print( join(".",(reverse @F),"in-addr.arpa"))'
: dig -x "$ip" | awk -F '[; t]+' '/^;.*PTR$/{print($2)}'
: host -t ptr 192.168.2.1 | cut -d' ' -f2

Both dig and host solutions work with IPv6.

Method 15

#!/bin/bash
# script file name reverseip.sh
if [ -z $1 ] || [ "help" == $1 ]
then
echo 'Convert a full ipv4 or ipv6 address to arpa notation'
echo "usage:"
echo ./reverseip.sh "help"
echo ./reverseip.sh "ipv4 address format: xxxx.xxxx.xxxx.xxxx"
echo ./reverseip.sh "ipv6 address format: xxxx:xxxx:xxxx:xxxx::xxxx"
echo "examples:"
echo ./reverseip.sh 216.58.207.35
echo ./reverseip.sh 2a00:1450:4001:824::2003
exit
fi

# if ip address passed containing ':'
if [[ $1 = *':'* ]];
then
# invert ipv6 address e.g.: 2a00:1450:4001:824::2003 to 3.0.0.2.0.0.0.0.0.0.0.0.0.0.0.0.4.2.8.0.1.0.0.4.0.5.4.1.0.0.a.2.
# @see lsowen https://gist.github.com/lsowen/4447d916fd19cbb7fce4
echo "$1" | awk -F: 'BEGIN {OFS=""; }{addCount = 9 - NF; for(i=1; i<=NF;i++){if(length($i) == 0){ for(j=1;j<=addCount;j++){$i = ($i "0000");} } else { $i = substr(("0000" $i), length($i)+5-4);}}; print}' | rev | sed -e "s/./&./g" | echo "$(</dev/stdin)ip6.arpa."
else
# invert ipv6 address e.g.: 216.58.207.35 to 35.207.58.216.in-addr.arpa
# @see Stéphane Chazelas https://unix.stackexchange.com/questions/132779/how-to-read-an-ip-address-backwards
echo $(printf %s "$1." | tac -s.)in-addr.arpa
fi

Method 16

With host command from dnsutils:

$ host -t ptr 192.168.1.1 | cut -d' ' -f 2
1.1.168.192.in-addr.arpa.

Method 17

A shorter alternative to mattbianco’s answer with less tools, but using pcregrep could be:

$ dig -x 194.68.208.240 | pcregrep -o1 '^;(S+)s+INs+PTR$'
240.208.68.194.in-addr.arpa.

$ dig -x 2001:db8:dc61:2a61::1 | pcregrep -o1 '^;(S+)s+INs+PTR$'
1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.1.6.a.2.1.6.c.d.8.b.d.0.1.0.0.2.ip6.arpa.

Method 18

Use following one line shell:

echo '192.168.1.1' | tr '.' 'n' | tac | paste -s -d '.' -

Method 19

Using POSIX sh:

$ ip=192.168.1.1
$ rev_ip=`
      IFS=.
      set -- $ip    # set positional parameters: $1, $2, $3, ...
      echo $4.$3.$2.$1.in-addr.arpa
  `
$ echo $rev_ip
1.1.168.192.in-addr.arpa

Note: Be careful when setting IFS. In my example, I isolated the internal field separator (IFS) in a subshell using the backtick operator, otherwise you may have to reset/restore it.

Alternatively, you could avoid IFS and use tr instead:

$ set -- `echo $ip | tr .  `
$ echo $4.$3.$2.$1.in-addr.arpa

If you’re using ksh or bash, use the $( ) subshell operator instead.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x