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