github.com/jcmturner/gokrb5/v8@v8.4.4/types/HostAddress.go (about)

     1  package types
     2  
     3  // Reference: https://www.ietf.org/rfc/rfc4120.txt
     4  // Section: 5.2.5
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"net"
    10  
    11  	"github.com/jcmturner/gofork/encoding/asn1"
    12  	"github.com/jcmturner/gokrb5/v8/iana/addrtype"
    13  )
    14  
    15  // HostAddresses implements RFC 4120 type: https://tools.ietf.org/html/rfc4120#section-5.2.5
    16  type HostAddresses []HostAddress
    17  
    18  // HostAddress implements RFC 4120 type: https://tools.ietf.org/html/rfc4120#section-5.2.5
    19  type HostAddress struct {
    20  	AddrType int32  `asn1:"explicit,tag:0"`
    21  	Address  []byte `asn1:"explicit,tag:1"`
    22  }
    23  
    24  // GetHostAddress returns a HostAddress struct from a string in the format <hostname>:<port>
    25  func GetHostAddress(s string) (HostAddress, error) {
    26  	var h HostAddress
    27  	cAddr, _, err := net.SplitHostPort(s)
    28  	if err != nil {
    29  		return h, fmt.Errorf("invalid format of client address: %v", err)
    30  	}
    31  	ip := net.ParseIP(cAddr)
    32  	var ht int32
    33  	if ip.To4() != nil {
    34  		ht = addrtype.IPv4
    35  		ip = ip.To4()
    36  	} else if ip.To16() != nil {
    37  		ht = addrtype.IPv6
    38  		ip = ip.To16()
    39  	} else {
    40  		return h, fmt.Errorf("could not determine client's address types: %v", err)
    41  	}
    42  	h = HostAddress{
    43  		AddrType: ht,
    44  		Address:  ip,
    45  	}
    46  	return h, nil
    47  }
    48  
    49  // GetAddress returns a string representation of the HostAddress.
    50  func (h *HostAddress) GetAddress() (string, error) {
    51  	var b []byte
    52  	_, err := asn1.Unmarshal(h.Address, &b)
    53  	return string(b), err
    54  }
    55  
    56  // LocalHostAddresses returns a HostAddresses struct for the local machines interface IP addresses.
    57  func LocalHostAddresses() (ha HostAddresses, err error) {
    58  	ifs, err := net.Interfaces()
    59  	if err != nil {
    60  		return
    61  	}
    62  	for _, iface := range ifs {
    63  		if iface.Flags&net.FlagLoopback != 0 || iface.Flags&net.FlagUp == 0 {
    64  			// Interface is either loopback of not up
    65  			continue
    66  		}
    67  		addrs, err := iface.Addrs()
    68  		if err != nil {
    69  			continue
    70  		}
    71  		for _, addr := range addrs {
    72  			var ip net.IP
    73  			switch v := addr.(type) {
    74  			case *net.IPNet:
    75  				ip = v.IP
    76  			case *net.IPAddr:
    77  				ip = v.IP
    78  			}
    79  			var a HostAddress
    80  			if ip.To16() == nil {
    81  				//neither IPv4 or IPv6
    82  				continue
    83  			}
    84  			if ip.To4() != nil {
    85  				//Is IPv4
    86  				a.AddrType = addrtype.IPv4
    87  				a.Address = ip.To4()
    88  			} else {
    89  				a.AddrType = addrtype.IPv6
    90  				a.Address = ip.To16()
    91  			}
    92  			ha = append(ha, a)
    93  		}
    94  	}
    95  	return ha, nil
    96  }
    97  
    98  // HostAddressesFromNetIPs returns a HostAddresses type from a slice of net.IP
    99  func HostAddressesFromNetIPs(ips []net.IP) (ha HostAddresses) {
   100  	for _, ip := range ips {
   101  		ha = append(ha, HostAddressFromNetIP(ip))
   102  	}
   103  	return ha
   104  }
   105  
   106  // HostAddressFromNetIP returns a HostAddress type from a net.IP
   107  func HostAddressFromNetIP(ip net.IP) HostAddress {
   108  	if ip.To4() != nil {
   109  		//Is IPv4
   110  		return HostAddress{
   111  			AddrType: addrtype.IPv4,
   112  			Address:  ip.To4(),
   113  		}
   114  	}
   115  	return HostAddress{
   116  		AddrType: addrtype.IPv6,
   117  		Address:  ip.To16(),
   118  	}
   119  }
   120  
   121  // HostAddressesEqual tests if two HostAddress slices are equal.
   122  func HostAddressesEqual(h, a []HostAddress) bool {
   123  	if len(h) != len(a) {
   124  		return false
   125  	}
   126  	for _, e := range a {
   127  		var found bool
   128  		for _, i := range h {
   129  			if e.Equal(i) {
   130  				found = true
   131  				break
   132  			}
   133  		}
   134  		if !found {
   135  			return false
   136  		}
   137  	}
   138  	return true
   139  }
   140  
   141  // HostAddressesContains tests if a HostAddress is contained in a HostAddress slice.
   142  func HostAddressesContains(h []HostAddress, a HostAddress) bool {
   143  	for _, e := range h {
   144  		if e.Equal(a) {
   145  			return true
   146  		}
   147  	}
   148  	return false
   149  }
   150  
   151  // Equal tests if the HostAddress is equal to another HostAddress provided.
   152  func (h *HostAddress) Equal(a HostAddress) bool {
   153  	if h.AddrType != a.AddrType {
   154  		return false
   155  	}
   156  	return bytes.Equal(h.Address, a.Address)
   157  }
   158  
   159  // Contains tests if a HostAddress is contained within the HostAddresses struct.
   160  func (h *HostAddresses) Contains(a HostAddress) bool {
   161  	for _, e := range *h {
   162  		if e.Equal(a) {
   163  			return true
   164  		}
   165  	}
   166  	return false
   167  }
   168  
   169  // Equal tests if a HostAddress slice is equal to the HostAddresses struct.
   170  func (h *HostAddresses) Equal(a []HostAddress) bool {
   171  	if len(*h) != len(a) {
   172  		return false
   173  	}
   174  	for _, e := range a {
   175  		if !h.Contains(e) {
   176  			return false
   177  		}
   178  	}
   179  	return true
   180  }