Skip to content

Instantly share code, notes, and snippets.

@ueokande
Last active June 18, 2024 18:26
Show Gist options
  • Save ueokande/05d3c03871048b7d996fa618d89d1a1b to your computer and use it in GitHub Desktop.
Save ueokande/05d3c03871048b7d996fa618d89d1a1b to your computer and use it in GitHub Desktop.
Calculating network addresses in tthe shell script
#!/bin/sh
# converts IPv4 as "A.B.C.D" to integer
# ip4_to_int 192.168.0.1
# => 3232235521
ip4_to_int() {
IFS=. read -r i j k l <<EOF
$1
EOF
echo $(( (i << 24) + (j << 16) + (k << 8) + l ))
}
# converts interger to IPv4 as "A.B.C.D"
#
# int_to_ip4 3232235521
# => 192.168.0.1
int_to_ip4() {
echo "$(( ($1 >> 24) % 256 )).$(( ($1 >> 16) % 256 )).$(( ($1 >> 8) % 256 )).$(( $1 % 256 ))"
}
# returns the ip part of an CIDR
#
# cidr_ip "172.16.0.10/22"
# => 172.16.0.10
cidr_ip() {
IFS=/ read -r ip _ <<EOF
$1
EOF
echo $ip
}
# returns the prefix part of an CIDR
#
# cidr_prefix "172.16.0.10/22"
# => 22
cidr_prefix() {
IFS=/ read -r _ prefix <<EOF
$1
EOF
echo $prefix
}
# returns net mask in numberic from prefix size
#
# netmask_of_prefix 8
# => 4278190080
netmask_of_prefix() {
echo $((4294967295 ^ (1 << (32 - $1)) - 1))
}
# returns default gateway address (network address + 1) from CIDR
cidr_default_gw() {
ip=$(ip4_to_int $(cidr_ip $1))
prefix=$(cidr_prefix $1)
netmask=$(netmask_of_prefix $prefix)
gw=$((ip & netmask + 1))
int_to_ip4 $gw
}
# returns default gateway address (broadcast address - 1) from CIDR
cidr_default_gw_2() {
ip=$(ip4_to_int $(cidr_ip $1))
prefix=$(cidr_prefix $1)
netmask=$(netmask_of_prefix $prefix)
broadcast=$(((4294967295 - netmask) | ip))
int_to_ip4 $((broadcast - 1))
}
cidr_default_gw 192.168.10.1/24
# => 192.168.10.1
cidr_default_gw 192.168.10.1/16
# => 192.168.0.1
cidr_default_gw 172.17.18.19/20
# => 172.17.16.1
cidr_default_gw_2 192.168.10.1/24
# => 192.168.10.254
cidr_default_gw_2 192.168.10.1/16
# => 192.168.255.254
cidr_default_gw_2 172.17.18.19/20
# => 172.17.31.254
@rkt2spc
Copy link

rkt2spc commented Dec 24, 2019

Very nice 🌚

@kalleboy
Copy link

kalleboy commented Mar 3, 2022

Any ipv6 version of this? Thanks.

@generesque
Copy link

This is great, but I think I found a bug in:

cidr_default_gw() {
  ip=$(ip4_to_int $(cidr_ip $1))
  prefix=$(cidr_prefix $1)
  netmask=$(netmask_of_prefix $prefix)
  gw=$((ip & netmask + 1))
  int_to_ip4 $gw
}

The order of operations of $((ip & netmask + 1)) means that netmask + 1 is done first. So if the IP is even, the gateway ends up as a x.y.z.0 instead of x.y.z.1. For odd IPs it works as expected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment