1 package routeable
2 3 import (
4 "errors"
5 "net"
6 "strings"
7 8 "github.com/jackpal/gateway"
9 )
10 11 // TODO: android and ios need equivalent functions as gateway.DiscoverGateway
12 13 // Gateway stores the current network default gateway as discovered by
14 // github.com/jackpal/gateway
15 var Gateway net.IP
16 17 // Address is the network address that routes to the gateway and thus the
18 // internet
19 var Address net.IP
20 21 // IPNet is the subnet of the Gateway's LAN
22 var IPNet *net.IPNet
23 24 // Interface is the net.Interface of the Address above
25 var Interface *net.Interface
26 //
27 // // SecondaryAddresses are all the other addresses that can be reached from
28 // // somewhere (including localhost) but not necessarily the internet
29 // var SecondaryAddresses []net.IP
30 //
31 // // SecondaryInterfaces is the interfaces of the SecondaryAddresses stored in the
32 // // corresponding slice index
33 // var SecondaryInterfaces []*net.Interface
34 35 // GetAddressesAndInterfaces returns all of the addresses and interfaces that
36 // would be resolved from an automatic addresses that can connect two processes at all
37 func GetAddressesAndInterfaces() (Interfaces []*net.Interface, Addresses map[string]struct{}) {
38 if Address == nil || Interface == nil {
39 if Discover() != nil {
40 E.Ln("no routeable address found")
41 }
42 }
43 Interfaces = append(Interfaces, Interface)
44 // Interfaces = append(Interfaces, SecondaryInterfaces...)
45 Addresses = make(map[string]struct{})
46 Addresses[Address.String()] = struct{}{}
47 // for i := range SecondaryAddresses {
48 // Addresses[SecondaryAddresses[i].String()] = struct{}{}
49 // }
50 // D.S(Interfaces)
51 // D.S(Addresses)
52 return
53 }
54 55 // Discover enumerates and evaluates all known network interfaces and addresses
56 // and filters it down to the ones that reach both a LAN and the internet
57 //
58 // We are only interested in IPv4 addresses because for the most part, domestic
59 // ISPs do not issue their customers with IPv6 routing, it's still a pain in the
60 // ass outside of large data centre connections
61 func Discover() (e error) {
62 D.Ln("discovering routeable interfaces and addresses...")
63 var nif []net.Interface
64 if nif, e = net.Interfaces(); E.Chk(e) {
65 return
66 }
67 // D.Ln("number of available network interfaces:", len(nif))
68 // D.S(nif)
69 var secondaryInterfaces []*net.Interface
70 var secondaryAddresses []net.IP
71 if Gateway, e = gateway.DiscoverGateway(); E.Chk(e) {
72 // todo: this error condition always happens on iOS and Android
73 // return
74 for i := range nif {
75 T.Ln(nif[i])
76 }
77 } else {
78 var gw net.IP
79 if Gateway != nil {
80 gws := Gateway.String()
81 gw = net.ParseIP(gws)
82 }
83 for i := range nif {
84 var addrs []net.Addr
85 if addrs, e = nif[i].Addrs(); E.Chk(e) || addrs == nil {
86 continue
87 }
88 for j := range addrs {
89 var in *net.IPNet
90 if _, in, e = net.ParseCIDR(addrs[j].String()); E.Chk(e) {
91 continue
92 }
93 if Gateway != nil && in.Contains(gw) {
94 Address = net.ParseIP(strings.Split(addrs[j].String(), "/")[0])
95 Interface = &nif[i]
96 IPNet = in
97 continue
98 }
99 ip, _, _ := net.ParseCIDR(addrs[j].String())
100 if strings.HasPrefix(ip.String(), "169.") || strings.HasPrefix(ip.String(), "fe80:") {
101 continue
102 }
103 if strings.HasPrefix(ip.String(), "127.") || strings.HasPrefix(ip.String(), "::1") {
104 continue
105 }
106 secondaryAddresses = append(secondaryAddresses, ip)
107 secondaryInterfaces = append(secondaryInterfaces, &nif[i])
108 }
109 }
110 }
111 // SecondaryAddresses = secondaryAddresses
112 // SecondaryInterfaces = secondaryInterfaces
113 T.Ln("Gateway", Gateway)
114 T.Ln("Address", Address)
115 T.Ln("Interface", Interface.Name)
116 // T.Ln("SecondaryAddresses")
117 // for i := range SecondaryInterfaces {
118 // T.Ln(SecondaryInterfaces[i].Name, SecondaryAddresses[i].String())
119 // }
120 return
121 }
122 123 // GetInterface returns the address and interface of multicast-and-internet capable interfaces
124 func GetInterface() (ifc *net.Interface, address string, e error) {
125 if Address == nil || Interface == nil {
126 if Discover() != nil {
127 e = errors.New("no routeable address found")
128 return
129 }
130 }
131 address = Address.String()
132 ifc = Interface
133 return
134 }
135 136 func GetListenable() net.IP {
137 if Address == nil {
138 if Discover() != nil {
139 E.Ln("no routeable address found")
140 }
141 }
142 return Address
143 }
144 145 func GetAllInterfacesAndAddresses() (interfaces []*net.Interface, udpAddrs []*net.UDPAddr) {
146 if Discover() != nil {
147 E.Ln("no routeable address found")
148 return
149 }
150 interfaces = []*net.Interface{Interface}
151 naddrs := []net.IP{Address}
152 var addrs []*net.IP
153 for i := range naddrs {
154 addrs = append(addrs, &naddrs[i])
155 }
156 var e error
157 for i := range addrs {
158 var udpAddr *net.UDPAddr
159 if udpAddr, e = net.ResolveUDPAddr("udp", addrs[i].String()+":0"); !E.Chk(e) {
160 udpAddrs = append(udpAddrs, udpAddr)
161 }
162 }
163 return
164 }
165