Skip to content

Commit

Permalink
feat: verify whether network contains another network
Browse files Browse the repository at this point in the history
  • Loading branch information
docent-net committed Jan 4, 2022
1 parent ce76c03 commit dfcff06
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 23 deletions.
14 changes: 11 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# ipcalc-contains
Golang micro-app, which check whether an IP address belongs to a given network
Golang micro-app, which check whether an IP address or a network belongs to a given network.

I use it as an addition to standard **ipcalc** binary distributed
with common Linux distributions.
Expand All @@ -14,10 +14,18 @@ I use it inside of my [Linux desktop deployment automation](https://github.com/d

![alt text](https://github.com/docent-net/ipcalc-contains/blob/main/static/docs-screenshot-usage.png?raw=true)

![alt text](https://github.com/docent-net/ipcalc-contains/blob/main/static/docs-screenshot-usage2.png?raw=true)

```bash
$ ./ipcalc-contains 192.168.0.0/24 192.168.0.10
$ ipcalc-contains 192.168.0.0/24 192.168.0.10
CONTAINS! Network 192.168.0.0/24 contains IP 192.168.0.10

$ ./ipcalc-contains 192.168.0.0/24 192.168.1.10
$ ipcalc-contains 192.168.0.0/24 192.168.1.10
NOPE! Network 192.168.0.0/24 DOES NOT contain 192.168.1.10

$ ipcalc-contains 192.168.0.0/20 192.168.12.0/30
CONTAINS! Network 192.168.0.0/20 contains 192.168.12.0/30

$ ipcalc-contains 192.168.1.0/20 192.168.12.128/10
NOPE! Network 192.168.1.0/20 DOES NOT contain 192.168.12.128/10
```
29 changes: 9 additions & 20 deletions cmd/contains.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,25 @@ package cmd
import (
"fmt"
"os"
"net"
"github.com/spf13/cobra"

"github.com/docent-net/ipcalc-contains/subnet"
)

var containsCmd = &cobra.Command{
Use: "contains",
Short: "Check whether first subnet (1st argument) contains IP addr (2nd argument)",
Long: `Check whether first subnet (1st argument) contains IP addr (2nd argument)`,
Short: "Check whether first subnet (1st argument) contains IP addr or other subnet (2nd argument)",
Long: `Check whether first subnet (1st argument) contains IP addr or other subnet (2nd argument)`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(subnetContains(args))
fmt.Println(getSubnetInfo(args))
},
}

func init() {
rootCmd.AddCommand(containsCmd)
}

func subnetContains(args []string) string {
func getSubnetInfo(args []string) string {
if ! verifyArgs(args) {
fmt.Println(`You must provide a subnet (slash notation, e.g.
192.168.0.0/24) and an IP address as exact 2 arguments for
Expand All @@ -30,24 +31,12 @@ Run --help for details`)
os.Exit(1)
}

_, ipv4Net, err := net.ParseCIDR(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}

ipv4Addr := net.ParseIP(args[1])
if ipv4Addr == nil {
fmt.Println(string(args[1]) + " is not recognized as IPv4 address")
os.Exit(1)
}

verificationString := ""

if ipv4Net.Contains(ipv4Addr) {
verificationString = fmt.Sprintf("CONTAINS! Network %s contains IP %s", ipv4Net, ipv4Addr)
if subnet.SubnetContains(args) {
verificationString = fmt.Sprintf("CONTAINS! Network %s contains %s", args[0], args[1])
} else {
verificationString = fmt.Sprintf("NOPE! Network %s DOES NOT contain %s", ipv4Net, ipv4Addr)
verificationString = fmt.Sprintf("NOPE! Network %s DOES NOT contain %s", args[0], args[1])
}
return verificationString
}
Expand Down
Binary file added static/docs-screenshot-usage-2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
66 changes: 66 additions & 0 deletions subnet/subnetContains.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package subnet

import (
"fmt"
"net"
"os"
)

func SubnetContains(args []string) bool {
// args[0]: should be a network in a slash notation: A.B.C.D/Y
// args[1]: should be an IP addr or a network in a slash notation

_, ipv4Net, err := net.ParseCIDR(args[0])
if err != nil {
fmt.Println(err)
os.Exit(1)
}

ipv4Addr := net.ParseIP(args[1])
if ipv4Addr == nil {
// maybe its a network?
_, ipv4Net2, err := net.ParseCIDR(args[1])
if err != nil {
fmt.Println(string(args[1]) + " is not recognized as IPv4 address nor a network")
os.Exit(1)
}
// checking if subnet contains another subnet:
if subnetContainsSubnet(ipv4Net, ipv4Net2) {
return true
}
} else {
// checking if subnet contains an IP addr:
if ipv4Net.Contains(ipv4Addr) {
return true
}
}

return false
}

func subnetContainsSubnet(net1 *net.IPNet, net2 *net.IPNet) bool {
// function verifies whether net1 contains net2

// for two networks A and B, if network A has smaller mask (lower number
// in slash notation), and network A consists B's IP address,
// than B is contained by A

// example:
//
// network A: 192.168.0.0/20
// network B: 192.168.12.0/30
//
// 1. network A has smaller mask (/20) than network's B mask (/30)
// 2. network A consists B's IP address 192.168.12.0
//
// thus network A 192.168.0.0/20 contains network B 192.168.12.0/30

net1Mask, _ := net1.Mask.Size()
net2Mask, _ := net2.Mask.Size()

if net1.Contains(net2.IP) && net2Mask >= net1Mask {
return true
}

return false
}

0 comments on commit dfcff06

Please sign in to comment.