0

I'm trying to write a Bash script that calculates the least common subnet for two address.

Theoretical: I have to change IP from decimal to binary, then apply XNOR on the two IPs.

I tried to write this:

#!/bin/bash
echo "Ebter the first ip"
read ip1
echo "Enter the second ip"
read ip2  

#Separate octs of first ip  

a1=`echo $ip1 | awk 'BEGIN{FS="."}{print $1}'`
a2=`echo $ip1 | awk 'BEGIN{FS="."}{print $2}'`
a3=`echo $ip1 | awk 'BEGIN{FS="."}{print $3}'`
a4=`echo $ip1 | awk 'BEGIN{FS="."}{print $4}'`  
#convert decimal to binary

b1=`echo "obase=2;$a1" | bc`
b2=`echo "obase=2;$a2" | bc`
b3=`echo "obase=2;$a3" | bc`
b4=`echo "obase=2;$a4" | bc`  

#Separate octs of second ip

c1=`echo $ip2 | awk 'BEGIN{FS="."}{print $1}'`
c2=`echo $ip2 | awk 'BEGIN{FS="."}{print $2}'`
c3=`echo $ip2 | awk 'BEGIN{FS="."}{print $3}'`
c4=`echo $ip2 | awk 'BEGIN{FS="."}{print $4}'`  

#convert decimal to binary (second IP)

d1=`echo "obase=2;$c1" | bc`
d2=`echo "obase=2;$c2" | bc`
d3=`echo "obase=2;$c3" | bc`
d4=`echo "obase=2;$c4" | bc`

e1=`echo $b1 || $d1 | rev`
e2=`echo $b2 || $d2 | rev`
e3=`echo $b3 || $d3 | rev`
e4=`echo $b4 || $d4 | rev`

echo "$e1.$e2.$e3.$e4"    

I have two problems:

  1. I need to apply XNOR to the binary IP (bit by bit), but if the result of a specific bit becomes zero I want to stop the operation and make another bit that follows the zero, zero also.

  2. I need that XNOR ignores ".".

Can someone help me with this issue please?

0

1 Answer 1

2

First, it's much simpler to use read to split the addresses into their integer parts.

IFS=. read a1 a2 a3 a4 <<< "$ip1"
IFS=. read b1 b2 b3 b4 <<< "$ip2"

Once you've done that, you can simply use shell arithmetic on each part; no need to explicitly convert each to binary first.

It's still a bit tricky to compute the mask in bash, though. Try this:

set_mask_part () {
    local m=255
    local a=$1
    local b=$2

    # While a and b are different, shift m left
    # and shift and b right. When a and b are equal,
    # the mask converges to the correct value.
    while (( a != b )); do
        (( m = (m << 1) & 255 ))
        (( a = a >> 1 ))
        (( b = b >> 1 ))
    done
    echo "$m"
}


# Get the left-most mask byte first, and repeat for
# each byte to the right as long as the previous byte is 255
m1=$(set_mask_part "$a1" "$b1")
(( m1 == 255 )) && m2=$(set_mask_part "$a2" "$b2") || m2=0
(( m2 == 255 )) && m3=$(set_mask_part "$a3" "$b3") || m3=0
(( m3 == 255 )) && m4=$(set_mask_part "$a4" "$b4") || m4=0

mask="$m1.$m2.$m3.$m4"
2
  • Thanks for ur answer, i wondering what about if the subnet is 224 for example. your script is just for 0 or 255 can u help me to complete my script, bec im beginner in bash and its easier for me. Thanks
    – Alaa Yalda
    Commented Feb 9, 2016 at 13:18
  • This isn't terribly well tested, but I get 255.255.255.224 for the addresses 192.0.2.4 and 192.0.2.17.
    – chepner
    Commented Feb 9, 2016 at 13:24

Not the answer you're looking for? Browse other questions tagged or ask your own question.