HostAddress.go 4.0 KB

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