randaddr.go 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142
  1. package main
  2. import (
  3. "crypto/rand"
  4. "fmt"
  5. "net"
  6. )
  7. // randIPAddr generates a random IP address within the network represented by
  8. // ipnet.
  9. func randIPAddr(ipnet *net.IPNet) (net.IP, error) {
  10. if len(ipnet.IP) != len(ipnet.Mask) {
  11. return nil, fmt.Errorf("IP and mask have unequal lengths (%v and %v)", len(ipnet.IP), len(ipnet.Mask))
  12. }
  13. ip := make(net.IP, len(ipnet.IP))
  14. _, err := rand.Read(ip)
  15. if err != nil {
  16. return nil, err
  17. }
  18. for i := 0; i < len(ipnet.IP); i++ {
  19. ip[i] = (ipnet.IP[i] & ipnet.Mask[i]) | (ip[i] & ^ipnet.Mask[i])
  20. }
  21. return ip, nil
  22. }
  23. // parseIPCIDR parses a CIDR-notation IP address and prefix length; or if that
  24. // fails, as a plain IP address (with the prefix length equal to the address
  25. // length).
  26. func parseIPCIDR(s string) (*net.IPNet, error) {
  27. _, ipnet, err := net.ParseCIDR(s)
  28. if err == nil {
  29. return ipnet, nil
  30. }
  31. // IP/mask failed; try just IP now, but remember err, to return it in
  32. // case that fails too.
  33. ip := net.ParseIP(s)
  34. if ip != nil {
  35. return &net.IPNet{IP: ip, Mask: net.CIDRMask(len(ip)*8, len(ip)*8)}, nil
  36. }
  37. return nil, err
  38. }