Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions cmd/in.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func newIn() *cli.Command {
return &cli.Command{
Name: "in",
Usage: "Determine if an ip falls within a range",
Usage: "Determine if an ip or range falls within one or more ranges",
Aliases: []string{"i"},
Action: func(_ context.Context, command *cli.Command) error {
args := command.Args().Slice()
Expand All @@ -19,6 +19,6 @@ func newIn() *cli.Command {

return handler.Handle(args)
},
UsageText: "in [ip] [range1] [optional range2] [optional rangeN]",
UsageText: "in [ip or range] [range1] [optional range2] [optional rangeN]",
}
}
38 changes: 20 additions & 18 deletions internal/cidr/cidr_block.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const (
)

type CIDRBlock struct {
Network string
HostPortion int
Network string
Host int
}

func NewBlock(network string) *CIDRBlock {
Expand All @@ -26,8 +26,8 @@ func NewBlock(network string) *CIDRBlock {
hostPortion := networkAndHostPortion[1]

return &CIDRBlock{
Network: networkPortion,
HostPortion: must(strconv.Atoi(hostPortion)),
Network: networkPortion,
Host: must(strconv.Atoi(hostPortion)),
}
}

Expand All @@ -41,10 +41,10 @@ func (b *CIDRBlock) Subnet(sizes []int) ([]string, error) {
subnetBlock := NewBlock(fmt.Sprintf("%s/%v", next.Network, size))

if !b.Contains(subnetBlock.Network) {
return nil, fmt.Errorf("invalid configuration: subnet %s/%v is outside provided network range %s/%v", next.Network, size, b.Network, b.HostPortion)
return nil, fmt.Errorf("invalid configuration: subnet %s/%v is outside provided network range %s/%v", next.Network, size, b.Network, b.Host)
}

subnets = append(subnets, fmt.Sprintf("%s/%v", subnetBlock.Network, subnetBlock.HostPortion))
subnets = append(subnets, fmt.Sprintf("%s/%v", subnetBlock.Network, subnetBlock.Host))

next = NewBlock(fmt.Sprintf("%s/%v", subnetBlock.StartAddressOfNextBlock(), size))
}
Expand All @@ -53,10 +53,12 @@ func (b *CIDRBlock) Subnet(sizes []int) ([]string, error) {
}

// https://stackoverflow.com/questions/9622967/how-to-see-if-an-ip-address-belongs-inside-of-a-range-of-ips-using-cidr-notation
func (b *CIDRBlock) Contains(ip string) bool {
IP_addr := ipToDecimal(ip)
CIDR_addr := ipToDecimal(b.Network)
CIDR_mask := -1 << (INT_SIZE - b.HostPortion)
func (outer *CIDRBlock) Contains(inner string) bool {
innerNetwork := strings.Split(inner, "/")[0]

IP_addr := ipToDecimal(innerNetwork)
CIDR_addr := ipToDecimal(outer.Network)
CIDR_mask := -1 << (INT_SIZE - outer.Host)

return (IP_addr & CIDR_mask) == (CIDR_addr & CIDR_mask)
}
Expand Down Expand Up @@ -88,9 +90,9 @@ func toBin(s string) string {
return paddedBynaryString
}

func (b *CIDRBlock) SubnetMask() string {
ones := strings.Repeat("1", b.HostPortion)
zeroes := strings.Repeat("0", INT_SIZE-b.HostPortion)
func (b *CIDRBlock) Mask() string {
ones := strings.Repeat("1", b.Host)
zeroes := strings.Repeat("0", INT_SIZE-b.Host)

mask := ones + zeroes

Expand All @@ -100,7 +102,7 @@ func (b *CIDRBlock) SubnetMask() string {
}

func (b *CIDRBlock) AvailableHosts() uint {
numAddresses := math.Pow(2, float64(INT_SIZE)-float64(b.HostPortion))
numAddresses := math.Pow(2, float64(INT_SIZE)-float64(b.Host))

return uint(numAddresses)
}
Expand Down Expand Up @@ -131,9 +133,9 @@ func (b *CIDRBlock) StartAddressOfNextBlock() string {
}

func (b *CIDRBlock) NetworkAddress() string {
ipBin := strings.ReplaceAll(b.NetworkPortionBinary(), ".", "")[0:b.HostPortion]
ipBin := strings.ReplaceAll(b.NetworkPortionBinary(), ".", "")[0:b.Host]

broadcast := ipBin + strings.Repeat("0", INT_SIZE-b.HostPortion)
broadcast := ipBin + strings.Repeat("0", INT_SIZE-b.Host)

octets := stringToOctets(broadcast)

Expand All @@ -142,9 +144,9 @@ func (b *CIDRBlock) NetworkAddress() string {

func (b *CIDRBlock) BroadcastAddress() string {
// https://stackoverflow.com/questions/1470792/how-to-calculate-the-ip-range-when-the-ip-address-and-the-netmask-is-given
ipBin := strings.ReplaceAll(b.NetworkPortionBinary(), ".", "")[0:b.HostPortion]
ipBin := strings.ReplaceAll(b.NetworkPortionBinary(), ".", "")[0:b.Host]

broadcast := ipBin + strings.Repeat("1", INT_SIZE-b.HostPortion)
broadcast := ipBin + strings.Repeat("1", INT_SIZE-b.Host)

octets := stringToOctets(broadcast)

Expand Down
12 changes: 7 additions & 5 deletions internal/cidr/cidr_block_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,10 @@ func Test_Contains(t *testing.T) {
ipRange *cidr.CIDRBlock
expected bool
}{
"ip inside range": {ip: "10.50.30.7", ipRange: cidr.NewBlock("10.0.0.0/8"), expected: true},
"ip outside range": {ip: "10.50.30.7", ipRange: cidr.NewBlock("10.0.0.0/28"), expected: false},
"ip inside range": {ip: "10.0.0.5", ipRange: cidr.NewBlock("10.0.0.0/28"), expected: true},
"ip outside range": {ip: "10.0.0.17", ipRange: cidr.NewBlock("10.0.0.0/28"), expected: false},
"range inside range": {ip: "10.0.0.4/30", ipRange: cidr.NewBlock("10.0.0.0/28"), expected: true},
"range outside range": {ip: "10.0.0.16/29", ipRange: cidr.NewBlock("10.0.0.0/28"), expected: false},
}

for name, test := range tests {
Expand Down Expand Up @@ -97,7 +99,7 @@ func Test_NetworkPortionBinary(t *testing.T) {
}
}

func Test_SubnetMask(t *testing.T) {
func Test_Mask(t *testing.T) {
tests := map[string]struct {
input *cidr.CIDRBlock
expected string
Expand Down Expand Up @@ -141,10 +143,10 @@ func Test_SubnetMask(t *testing.T) {
t.Run(name, func(t *testing.T) {
t.Parallel()

actual := test.input.SubnetMask()
actual := test.input.Mask()

if actual != test.expected {
t.Fatalf("%s returns correct subnet mask: got %v expected %v", name, actual, test.expected)
t.Fatalf("%s returns correct mask: got %v expected %v", name, actual, test.expected)
}
})
}
Expand Down
10 changes: 5 additions & 5 deletions internal/commands/in/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@ func (h *handler) Handle(args []string) error {
return fmt.Errorf("command expects at least 2 arguments")
}

ip := args[0]

ranges := list.Map(args[1:], func(i string) *cidr.CIDRBlock {
return cidr.NewBlock(i)
})

ipOrRange := args[0]

blocksInRange := list.Filter(ranges, func(cidr *cidr.CIDRBlock) bool {
return cidr.Contains(ip)
return cidr.Contains(ipOrRange)
})

if len(blocksInRange) == 0 {
fmt.Printf("%s is not in any of the provided ranges\n", ip)
fmt.Printf("%s is not in any of the provided ranges\n", ipOrRange)
return nil
}

for _, block := range blocksInRange {
fmt.Printf("%s/%d\n", block.Network, block.HostPortion)
fmt.Printf("%s/%d\n", block.Network, block.Host)
}

return nil
Expand Down
2 changes: 1 addition & 1 deletion internal/commands/info/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (h *handler) Handle(args []string) error {
entries := []pair{
{item1: "Address range", item2: fmt.Sprintf("%s - %s", block.NetworkAddress(), block.BroadcastAddress())},
{item1: "Start of next block", item2: block.StartAddressOfNextBlock()},
{item1: "Mask", item2: fmt.Sprintf("%s (%s)", fmt.Sprintf("/%v", block.HostPortion), block.SubnetMask())},
{item1: "Mask", item2: fmt.Sprintf("%s (%s)", fmt.Sprintf("/%v", block.Host), block.Mask())},
{item1: "Addresses", item2: fmt.Sprintf("%v", block.AvailableHosts())},
{item1: "Azure addresses", item2: block.AvailableAzureHosts()},
}
Expand Down
4 changes: 2 additions & 2 deletions internal/commands/ranges/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ func defaultCidrBlockFromHostPortion(hostPortion int) *cidr.CIDRBlock {
func printCidrBlocks(blocks []*cidr.CIDRBlock) error {
w := tabwriter.NewWriter(os.Stdout, 2, 4, 1, ' ', 0)

fmt.Fprint(w, "Cidr\tSubnet mask\tAddresses\tAzure addresses\n")
fmt.Fprint(w, "Cidr\tMask\tAddresses\tAzure addresses\n")
for _, block := range blocks {
fmt.Fprintf(w, "/%v\t%s\t%v\t%s\n", block.HostPortion, block.SubnetMask(), block.AvailableHosts(), block.AvailableAzureHosts())
fmt.Fprintf(w, "/%v\t%s\t%v\t%s\n", block.Host, block.Mask(), block.AvailableHosts(), block.AvailableAzureHosts())
}

return w.Flush()
Expand Down