@@ -27,10 +27,10 @@ be overridden using environment variables:
2727 SCION_DISPATCHER_SOCKET: /run/shm/dispatcher/default.sock
2828 SCION_DAEMON_ADDRESS: 127.0.0.1:30255
2929
30- This is convenient for the normal use case of running a the endhost stack for
31- a single SCION AS. When running multiple local ASes, e.g. during development, the path
32- to the sciond corresponding to the desired AS needs to be specified in the
33- SCION_DAEMON_ADDRESS environment variable.
30+ This is convenient for the normal use case of running a the endhost stack for a
31+ single SCION AS. When running multiple local ASes, e.g. during development, the
32+ address of the sciond corresponding to the desired AS needs to be specified in
33+ the SCION_DAEMON_ADDRESS environment variable.
3434
3535
3636Wildcard IP Addresses
@@ -55,10 +55,12 @@ import (
5555 "net"
5656 "os"
5757 "sync"
58+ "time"
5859
5960 "github.com/scionproto/scion/go/lib/addr"
6061 "github.com/scionproto/scion/go/lib/sciond"
6162 "github.com/scionproto/scion/go/lib/snet"
63+ "github.com/scionproto/scion/go/lib/snet/addrutil"
6264 "github.com/scionproto/scion/go/lib/sock/reliable"
6365)
6466
@@ -73,6 +75,10 @@ type Network struct {
7375 hostInLocalAS net.IP
7476}
7577
78+ const (
79+ initTimeout = 1 * time .Second
80+ )
81+
7682var defNetwork Network
7783var initOnce sync.Once
7884
@@ -87,7 +93,7 @@ func DefNetwork() *Network {
8793// Dial connects to the address (on the SCION/UDP network).
8894// The address can be of the form of a SCION address (i.e. of the form "ISD-AS,[IP]:port")
8995// or in the form of hostname:port.
90- func Dial (address string ) (snet.Conn , error ) {
96+ func Dial (address string ) (* snet.Conn , error ) {
9197 raddr , err := ResolveUDPAddr (address )
9298 if err != nil {
9399 return nil , err
@@ -102,51 +108,58 @@ func Dial(address string) (snet.Conn, error) {
102108// support long lived connections well, as the path *will* expire.
103109// This is all that snet currently provides, we'll need to add a layer on top
104110// that updates the paths in case they expire or are revoked.
105- func DialAddr (raddr * snet.UDPAddr ) (snet.Conn , error ) {
111+ func DialAddr (raddr * snet.UDPAddr ) (* snet.Conn , error ) {
106112 if raddr .Path == nil {
107113 err := SetDefaultPath (raddr )
108114 if err != nil {
109115 return nil , err
110116 }
111117 }
112- laddr := & net.UDPAddr {IP : localIP (raddr )}
113- return DefNetwork ().Dial (context .TODO (), "udp" , laddr , raddr , addr .SvcNone )
118+ localIP , err := resolveLocal (raddr )
119+ if err != nil {
120+ return nil , err
121+ }
122+ laddr := & net.UDPAddr {IP : localIP }
123+ return DefNetwork ().Dial (context .Background (), "udp" , laddr , raddr , addr .SvcNone )
114124}
115125
116126// Listen acts like net.ListenUDP in a SCION network.
117127// The listen address or parts of it may be nil or unspecified, signifying to
118128// listen on a wildcard address.
119129//
120130// See note on wildcard addresses in the package documentation.
121- func Listen (listen * net.UDPAddr ) (snet.Conn , error ) {
131+ func Listen (listen * net.UDPAddr ) (* snet.Conn , error ) {
122132 if listen == nil {
123133 listen = & net.UDPAddr {}
124134 }
125135 if listen .IP == nil || listen .IP .IsUnspecified () {
126- listen = & net.UDPAddr {IP : defaultLocalIP (), Port : listen .Port , Zone : listen .Zone }
136+ localIP , err := defaultLocalIP ()
137+ if err != nil {
138+ return nil , err
139+ }
140+ listen = & net.UDPAddr {IP : localIP , Port : listen .Port , Zone : listen .Zone }
127141 }
128- return DefNetwork ().Listen (context .TODO (), "udp" , listen , addr .SvcNone )
142+ return DefNetwork ().Listen (context .Background (), "udp" , listen , addr .SvcNone )
129143}
130144
131145// ListenPort is a shortcut to Listen on a specific port with a wildcard IP address.
132146//
133147// See note on wildcard addresses in the package documentation.
134- func ListenPort (port uint16 ) (snet.Conn , error ) {
135- listen := & net.UDPAddr {IP : defaultLocalIP (), Port : int (port )}
136- return DefNetwork ().Listen (context .TODO (), "udp" , listen , addr .SvcNone )
148+ func ListenPort (port uint16 ) (* snet.Conn , error ) {
149+ return Listen (& net.UDPAddr {Port : int (port )})
137150}
138151
139- // localAddr returns the source IP address for traffic to raddr. If
152+ // resolveLocal returns the source IP address for traffic to raddr. If
140153// raddr.NextHop is set, it's used to determine the local IP address.
141154// Otherwise, the default local IP address is returned.
142155//
143156// The purpose of this function is to workaround not being able to bind to
144157// wildcard addresses in snet.
145158// See note on wildcard addresses in the package documentation.
146- func localIP (raddr * snet.UDPAddr ) net.IP {
159+ func resolveLocal (raddr * snet.UDPAddr ) ( net.IP , error ) {
147160 if raddr .NextHop != nil {
148161 nextHop := raddr .NextHop .IP
149- return findSrcIP (nextHop )
162+ return addrutil . ResolveLocal (nextHop )
150163 }
151164 return defaultLocalIP ()
152165}
@@ -156,8 +169,8 @@ func localIP(raddr *snet.UDPAddr) net.IP {
156169// The purpose of this function is to workaround not being able to bind to
157170// wildcard addresses in snet.
158171// See note on wildcard addresses in the package documentation.
159- func defaultLocalIP () net.IP {
160- return findSrcIP (DefNetwork ().hostInLocalAS )
172+ func defaultLocalIP () ( net.IP , error ) {
173+ return addrutil . ResolveLocal (DefNetwork ().hostInLocalAS )
161174}
162175
163176func mustInitDefNetwork () {
@@ -169,19 +182,21 @@ func mustInitDefNetwork() {
169182}
170183
171184func initDefNetwork () error {
185+ ctx , cancel := context .WithTimeout (context .Background (), initTimeout )
186+ defer cancel ()
172187 dispatcher , err := findDispatcher ()
173188 if err != nil {
174189 return err
175190 }
176- sciondConn , err := findSciond ()
191+ sciondConn , err := findSciond (ctx )
177192 if err != nil {
178193 return err
179194 }
180- localIA , err := findLocalIA ( sciondConn )
195+ localIA , err := sciondConn . LocalIA ( ctx )
181196 if err != nil {
182197 return err
183198 }
184- hostInLocalAS , err := findAnyHostInLocalAS (sciondConn )
199+ hostInLocalAS , err := findAnyHostInLocalAS (ctx , sciondConn )
185200 if err != nil {
186201 return err
187202 }
@@ -196,12 +211,12 @@ func initDefNetwork() error {
196211 return nil
197212}
198213
199- func findSciond () (sciond.Connector , error ) {
214+ func findSciond (ctx context. Context ) (sciond.Connector , error ) {
200215 address , ok := os .LookupEnv ("SCION_DAEMON_ADDRESS" )
201216 if ! ok {
202217 address = sciond .DefaultSCIONDAddress
203218 }
204- sciondConn , err := sciond .NewService (address ).Connect (context . Background () )
219+ sciondConn , err := sciond .NewService (address ).Connect (ctx )
205220 if err != nil {
206221 return nil , fmt .Errorf ("unable to connect to SCIOND at %s (override with SCION_DAEMON_ADDRESS): %w" , address , err )
207222 }
@@ -244,28 +259,9 @@ func isSocket(mode os.FileMode) bool {
244259 return mode & os .ModeSocket != 0
245260}
246261
247- func findLocalIA (sciondConn sciond.Connector ) (addr.IA , error ) {
248- asInfo , err := sciondConn .ASInfo (context .TODO (), addr.IA {})
249- if err != nil {
250- return addr.IA {}, err
251- }
252- ia := asInfo .Entries [0 ].RawIsdas .IA ()
253- return ia , nil
254- }
255-
256- // findSrcIP returns the src IP used for traffic destined to dst
257- func findSrcIP (dst net.IP ) net.IP {
258- // Use net.Dial to lookup source address. Alternatively, could use netlink.
259- udpAddr := net.UDPAddr {IP : dst , Port : 1 }
260- udpConn , _ := net .DialUDP (udpAddr .Network (), nil , & udpAddr )
261- srcIP := udpConn .LocalAddr ().(* net.UDPAddr ).IP
262- udpConn .Close ()
263- return srcIP
264- }
265-
266262// findAnyHostInLocalAS returns the IP address of some (infrastructure) host in the local AS.
267- func findAnyHostInLocalAS (sciondConn sciond.Connector ) (net.IP , error ) {
268- addr , err := sciond.TopoQuerier {Connector : sciondConn }.OverlayAnycast (context . Background () , addr .SvcBS )
263+ func findAnyHostInLocalAS (ctx context. Context , sciondConn sciond.Connector ) (net.IP , error ) {
264+ addr , err := sciond.TopoQuerier {Connector : sciondConn }.OverlayAnycast (ctx , addr .SvcBS )
269265 if err != nil {
270266 return nil , err
271267 }
0 commit comments