package kyoketsu import ( "fmt" "log" "net" "net/netip" "strconv" "strings" ) type NetworkInterfaceNotFound struct{ Passed string } // Implementing error interface func (n *NetworkInterfaceNotFound) Error() string { return fmt.Sprintf("Interface: '%s' not found.", n.Passed) } type IpSubnetMapper struct { Ipv4s []net.IP `json:"addresses"` NetworkAddr net.IP Current net.IP Mask int } /* Get the next IPv4 address of the address specified in the 'addr' argument, :param addr: the address to get the next address of */ func getNextAddr(addr string) string { parsed, err := netip.ParseAddr(addr) if err != nil { log.Fatal("failed while parsing address in getNextAddr() ", err, "\n") } return parsed.Next().String() } /* get the network address of the ip address in 'addr' with the subnet mask from 'cidr' :param addr: the ipv4 address to get the network address of :param cidr: the CIDR notation of the subbet */ func getNetwork(addr string, cidr int) string { addr = fmt.Sprintf("%s/%v", addr, cidr) ip, net, err := net.ParseCIDR(addr) if err != nil { log.Fatal("failed whilst attempting to parse cidr in getNetwork() ", err, "\n") } return ip.Mask(net.Mask).String() } /* Recursive function to get all of the IPv4 addresses for each IPv4 network that the host is on :param ipmap: a pointer to an IpSubnetMapper struct which contains domain details such as the subnet mask, the original network mask, and the current IP address used in the recursive function :param max: This is safety feature to prevent stack overflows, so you can manually set the depth to call the function */ func addressRecurse(ipmap *IpSubnetMapper) { next := getNextAddr(ipmap.Current.String()) nextNet := getNetwork(next, ipmap.Mask) currentNet := ipmap.NetworkAddr.String() if nextNet != currentNet { return } ipmap.Current = net.ParseIP(next) ipmap.Ipv4s = append(ipmap.Ipv4s, net.ParseIP(next)) addressRecurse(ipmap) } /* Get all of the IPv4 addresses in the network that 'addr' belongs to. YOU MUST PASS THE ADDRESS WITH CIDR NOTATION i.e. '192.168.50.1/24' :param addr: the ipv4 address to use for subnet discovery */ func GetNetworkAddresses(addr string) (*IpSubnetMapper, error) { ipmap := &IpSubnetMapper{Ipv4s: []net.IP{}} ip, net, err := net.ParseCIDR(addr) if err != nil { return nil, err } mask, err := strconv.Atoi(strings.Split(addr, "/")[1]) if err != nil { return nil, err } ipmap.NetworkAddr = ip.Mask(net.Mask) ipmap.Mask = mask ipmap.Current = ip.Mask(net.Mask) addressRecurse(ipmap) return ipmap, nil }