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"
Sign up to request clarification or add additional context in comments.

2 Comments

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
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.