Repository: scionproto/scion
Pull request #3521 (2019-12-16 08:46:41)

snet: refactor Listens and Dials (#1694)
- Remove bind
- Use a single method Listen / Dial
- Use {s}net.UDPAddr as arguments
- Improve naming of arguments

Contributes #3136

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/scionproto/scion/3521)
<!-- Reviewable:end -->



Patch:
diff --git a/go/border/rctrl/ctrl.go b/go/border/rctrl/ctrl.go
index e51f71de5..2a20d9800 100644
--- a/go/border/rctrl/ctrl.go
+++ b/go/border/rctrl/ctrl.go
@@ -57,8 +57,7 @@ func Control(sRevInfoQ chan rpkt.RawSRevCallbackArgs, dispatcherReconnect bool)
 		},
 	)
 	ctrlAddr := ctx.Conf.BR.CtrlAddrs
-	pub := snet.NewUDPAddr(ia, nil, nil, ctrlAddr.SCIONAddress)
-	snetConn, err = scionNetwork.ListenSCIONWithBindSVC("udp4", pub.ToAddr(), nil, addr.SvcNone, 0)
+	snetConn, err = scionNetwork.Listen("udp4", ctrlAddr.SCIONAddress, addr.SvcNone, 0)
 	if err != nil {
 		fatal.Fatal(common.NewBasicError("Listening on address", err, "addr", ctrlAddr))
 	}
diff --git a/go/examples/pingpong/BUILD.bazel b/go/examples/pingpong/BUILD.bazel
index b008af228..8e9c67c80 100644
--- a/go/examples/pingpong/BUILD.bazel
+++ b/go/examples/pingpong/BUILD.bazel
@@ -7,6 +7,7 @@ go_library(
     importpath = "github.com/scionproto/scion/go/examples/pingpong",
     visibility = ["//visibility:private"],
     deps = [
+        "//go/lib/addr:go_default_library",
         "//go/lib/common:go_default_library",
         "//go/lib/integration:go_default_library",
         "//go/lib/log:go_default_library",
diff --git a/go/examples/pingpong/pingpong.go b/go/examples/pingpong/pingpong.go
index e158aefbc..7b89a7d4c 100644
--- a/go/examples/pingpong/pingpong.go
+++ b/go/examples/pingpong/pingpong.go
@@ -34,6 +34,7 @@ import (
 
 	"github.com/lucas-clemente/quic-go"
 
+	"github.com/scionproto/scion/go/lib/addr"
 	"github.com/scionproto/scion/go/lib/common"
 	"github.com/scionproto/scion/go/lib/integration"
 	"github.com/scionproto/scion/go/lib/log"
@@ -219,7 +220,7 @@ func newClient() *client {
 // while receiving pong messages. For each successful ping-pong, a message
 // with the round trip time is printed.
 func (c *client) run() {
-	// Needs to happen before DialSCION, as it will 'copy' the remote to the connection.
+	// Needs to happen before Dial, as it will 'copy' the remote to the connection.
 	// If remote is not in local AS, we need a path!
 	c.setupPath()
 	defer c.Close()
@@ -237,9 +238,10 @@ func (c *client) run() {
 	// Connect to remote address. Note that currently the SCION library
 	// does not support automatic binding to local addresses, so the local
 	// IP address needs to be supplied explicitly. When supplied a local
-	// port of 0, DialSCION will assign a random free local port.
+	// port of 0, Dial will assign a random free local port.
 
-	c.qsess, err = squic.DialSCION(network, &local, &remote, nil)
+	remoteUDP := snet.NewUDPAddr(remote.IA, remote.Path, remote.NextHop, remote.ToNetUDPAddr())
+	c.qsess, err = squic.Dial(network, local.ToNetUDPAddr(), remoteUDP, addr.SvcNone, nil)
 	if err != nil {
 		LogFatal("Unable to dial", "err", err)
 	}
@@ -359,13 +361,13 @@ func (s server) run() {
 	if err != nil {
 		LogFatal("Unable to initialize SCION network", "err", err)
 	}
-	qsock, err := squic.ListenSCION(network, &local, nil)
+	qsock, err := squic.Listen(network, local.ToNetUDPAddr(), addr.SvcNone, nil)
 	if err != nil {
 		LogFatal("Unable to listen", "err", err)
 	}
 	if len(os.Getenv(integration.GoIntegrationEnv)) > 0 {
 		// Needed for integration test ready signal.
-		fmt.Printf("Port=%d\n", qsock.Addr().(*snet.Addr).Host.L4)
+		fmt.Printf("Port=%d\n", qsock.Addr().(*net.UDPAddr).Port)
 		fmt.Printf("%s%s\n", integration.ReadySignal, local.IA)
 	}
 	log.Info("Listening", "local", qsock.Addr())
diff --git a/go/integration/cert_req/main.go b/go/integration/cert_req/main.go
index 40bc12f41..927b4d116 100644
--- a/go/integration/cert_req/main.go
+++ b/go/integration/cert_req/main.go
@@ -65,7 +65,7 @@ type client struct {
 func (c client) run() int {
 	network := integration.InitNetwork()
 	var err error
-	c.conn, err = network.ListenSCION("udp4", &integration.Local, 0)
+	c.conn, err = network.Listen("udp4", integration.Local.ToNetUDPAddr(), addr.SvcNone, 0)
 	if err != nil {
 		integration.LogFatal("Unable to listen", "err", err)
 	}
diff --git a/go/lib/infra/infraenv/infraenv.go b/go/lib/infra/infraenv/infraenv.go
index a1cf43c6e..451bc7cd2 100644
--- a/go/lib/infra/infraenv/infraenv.go
+++ b/go/lib/infra/infraenv/infraenv.go
@@ -20,6 +20,7 @@ import (
 	"bytes"
 	"context"
 	"crypto/tls"
+	"fmt"
 	"net"
 	"time"
 
@@ -96,7 +97,7 @@ func (nc *NetworkConfig) Messenger() (infra.Messenger, error) {
 		if err != nil {
 			return nil, err
 		}
-		quicAddress = quicConn.LocalAddr().(*snet.Addr).Host.String()
+		quicAddress = fmt.Sprintf("%s", quicConn.LocalAddr()) // assuming net.UDPAddr.
 		log.Trace("QUIC conn initialized", "local_addr", quicAddress)
 	}
 
@@ -199,12 +200,7 @@ func (nc *NetworkConfig) initUDPSocket(quicAddress string) (net.PacketConn, erro
 		},
 	)
 	network := snet.NewCustomNetworkWithPR(nc.IA, packetDispatcher)
-	var listenAddr *snet.Addr
-	if nc.Public != nil {
-		listenAddr = &snet.Addr{IA: nc.IA, Host: addr.AppAddrFromUDP(nc.Public)}
-	}
-
-	conn, err := network.ListenSCIONWithBindSVC("udp4", listenAddr, nil, nc.SVC, 0)
+	conn, err := network.Listen("udp4", nc.Public, nc.SVC, 0)
 	if err != nil {
 		return nil, common.NewBasicError("Unable to listen on SCION", err)
 	}
@@ -223,19 +219,11 @@ func (nc *NetworkConfig) initQUICSocket() (net.PacketConn, error) {
 			SCMPHandler: ignoreSCMP{},
 		},
 	)
-	// FIXME(scrye): Add support for bind addresses.
 	udpAddr, err := net.ResolveUDPAddr("udp", nc.QUIC.Address)
 	if err != nil {
 		return nil, common.NewBasicError("Unable to parse address", err)
 	}
-	public := &snet.Addr{
-		IA: nc.IA,
-		Host: &addr.AppAddr{
-			L3: addr.HostFromIP(udpAddr.IP),
-			L4: uint16(udpAddr.Port),
-		},
-	}
-	conn, err := network.ListenSCIONWithBindSVC("udp4", public, nil, addr.SvcNone, 0)
+	conn, err := network.Listen("udp4", udpAddr, addr.SvcNone, 0)
 	if err != nil {
 		return nil, common.NewBasicError("Unable to listen on SCION", err)
 	}
diff --git a/go/lib/sciond/pathprobe/paths.go b/go/lib/sciond/pathprobe/paths.go
index 10186b9a8..40d3584c0 100644
--- a/go/lib/sciond/pathprobe/paths.go
+++ b/go/lib/sciond/pathprobe/paths.go
@@ -117,7 +117,8 @@ func (p Prober) GetStatuses(ctx context.Context,
 			SCMPHandler: scmpH,
 		},
 	)
-	snetConn, err := network.ListenSCION("udp4", &p.Local, deadline.Sub(time.Now()))
+	snetConn, err := network.Listen("udp4", p.Local.ToNetUDPAddr(),
+		addr.SvcNone, deadline.Sub(time.Now()))
 	if err != nil {
 		return nil, common.NewBasicError("listening failed", err)
 	}
diff --git a/go/lib/snet/base.go b/go/lib/snet/base.go
index 5c639b9e0..497e57dd3 100644
--- a/go/lib/snet/base.go
+++ b/go/lib/snet/base.go
@@ -1,4 +1,5 @@
 // Copyright 2018 ETH Zurich
+// Copyright 2019 ETH Zurich, Anapaya Systems
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -21,10 +22,9 @@ import (
 )
 
 type scionConnBase struct {
-	// Local, remote and bind SCION addresses (IA, L3, L4)
-	laddr *Addr
-	raddr *Addr
-	baddr *Addr
+	// Local and remote SCION addresses (IA, L3, L4)
+	listen *net.UDPAddr
+	remote *UDPAddr
 
 	// svc address
 	svc addr.HostSVC
@@ -36,28 +36,12 @@ type scionConnBase struct {
 	net string
 }
 
-func (c *scionConnBase) BindAddr() net.Addr {
-	return c.baddr
-}
-
-func (c *scionConnBase) BindSnetAddr() *Addr {
-	return c.baddr
-}
-
 func (c *scionConnBase) LocalAddr() net.Addr {
-	return c.laddr
-}
-
-func (c *scionConnBase) LocalSnetAddr() *Addr {
-	return c.laddr
+	return c.listen
 }
 
 func (c *scionConnBase) RemoteAddr() net.Addr {
-	return c.raddr
-}
-
-func (c *scionConnBase) RemoteSnetAddr() *Addr {
-	return c.raddr
+	return c.remote
 }
 
 func (c *scionConnBase) SVC() addr.HostSVC {
diff --git a/go/lib/snet/interface.go b/go/lib/snet/interface.go
index f24d68c43..2e2757f9f 100644
--- a/go/lib/snet/interface.go
+++ b/go/lib/snet/interface.go
@@ -1,4 +1,5 @@
 // Copyright 2018 ETH Zurich
+// Copyright 2019 ETH Zurich, Anapaya Systems
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -22,10 +23,10 @@ import (
 )
 
 type Network interface {
-	ListenSCIONWithBindSVC(network string,
-		laddr, baddr *Addr, svc addr.HostSVC, timeout time.Duration) (Conn, error)
-	DialSCIONWithBindSVC(network string,
-		laddr, raddr, baddr *Addr, svc addr.HostSVC, timeout time.Duration) (Conn, error)
+	Listen(network string, listen *net.UDPAddr, svc addr.HostSVC,
+		timeout time.Duration) (Conn, error)
+	Dial(network string, listen *net.UDPAddr, remote *UDPAddr, svc addr.HostSVC,
+		timeout time.Duration) (Conn, error)
 }
 
 // Conn represents a SCION connection.
@@ -38,7 +39,6 @@ type Conn interface {
 	WriteToSCION(b []byte, address *Addr) (int, error)
 	Close() error
 	LocalAddr() net.Addr
-	BindAddr() net.Addr
 	SVC() addr.HostSVC
 	// RemoteAddr returns the remote network address.
 	RemoteAddr() net.Addr
diff --git a/go/lib/snet/snet.go b/go/lib/snet/snet.go
index 68ef382f0..40e5a54ef 100644
--- a/go/lib/snet/snet.go
+++ b/go/lib/snet/snet.go
@@ -16,20 +16,18 @@
 // Package snet implements interfaces net.Conn and net.PacketConn for SCION
 // connections.
 //
-// New networking contexts can be created using NewNetwork. Calling the
-// DialSCION or ListenSCION methods on the networking context yields
-// connections that run in that context.
+// New networking contexts can be created using NewNetwork. Calling the Dial or
+// Listen methods on the networking context yields connections that run in that
+// context.
 //
-// A connection can be created by calling DialSCION or ListenSCION; both
-// functions register an address-port pair with the local dispatcher. For Dial,
-// the remote address is fixed, meaning only Read and Write can be used.
-// Attempting to ReadFrom or WriteTo a connection created by Dial is an invalid
-// operation. For Listen, the remote address cannot be fixed. ReadFrom,
-// ReadFromSCION can be used to read from the connection and find out the
-// sender's address; WriteTo and WriteToSCION can be used to send a message to
-// a chosen destination.
+// A connection can be created by calling Dial or Listen; both functions
+// register an address-port pair with the local dispatcher. For Dial, the remote
+// address is fixed, meaning only Read and Write can be used. Attempting to
+// ReadFrom or WriteTo a connection created by Dial is an invalid operation. For
+// Listen, the remote address cannot be fixed. ReadFrom, ReadFromSCION can be
+// used to read from the connection and find out the sender's address; WriteTo
+// and WriteToSCION can be used to send a message to a chosen destination.
 //
-
 // Multiple networking contexts can share the same SCIOND and/or dispatcher.
 //
 // Write calls never return SCMP errors directly. If a write call caused an
@@ -95,61 +93,36 @@ func NewCustomNetworkWithPR(ia addr.IA, pktDispatcher PacketDispatcherService) *
 	}
 }
 
-// DialSCION returns a SCION connection to raddr. Nil values for laddr are not
+// Dial returns a SCION connection to remote. Nil values for listen are not
 // supported yet.  Parameter network must be "udp4". The returned connection's
 // Read and Write methods can be used to receive and send SCION packets.
 //
 // The timeout is used for connection setup, it doesn't affect the returned
 // connection. A timeout of 0 means infinite timeout.
-func (n *SCIONNetwork) DialSCION(network string, laddr, raddr *Addr,
-	timeout time.Duration) (Conn, error) {
-
-	return n.DialSCIONWithBindSVC(network, laddr, raddr, nil, addr.SvcNone, timeout)
-}
-
-// DialSCIONWithBindSVC returns a SCION connection to raddr. Nil values for laddr are not
-// supported yet.  Parameter network must be "udp4". The returned connection's
-// Read and Write methods can be used to receive and send SCION packets.
-//
-// The timeout is used for connection setup, it doesn't affect the returned
-// connection. A timeout of 0 means infinite timeout.
-func (n *SCIONNetwork) DialSCIONWithBindSVC(network string, laddr, raddr, baddr *Addr,
+func (n *SCIONNetwork) Dial(network string, listen *net.UDPAddr, remote *UDPAddr,
 	svc addr.HostSVC, timeout time.Duration) (Conn, error) {
 
 	metrics.M.Dials().Inc()
-	if raddr == nil {
+	if remote == nil {
 		return nil, serrors.New("Unable to dial to nil remote")
 	}
-	conn, err := n.ListenSCIONWithBindSVC(network, laddr, baddr, svc, timeout)
+	conn, err := n.Listen(network, listen, svc, timeout)
 	if err != nil {
 		return nil, err
 	}
 	snetConn := conn.(*SCIONConn)
-	snetConn.raddr = raddr.Copy()
+	snetConn.remote = NewUDPAddr(remote.IA, remote.Path.Copy(), remote.NextHop, remote.Host)
 	return conn, nil
 }
 
-// ListenSCION registers laddr with the dispatcher. Nil values for laddr are
-// not supported yet. The returned connection's ReadFrom and WriteTo methods
-// can be used to receive and send SCION packets with per-packet addressing.
-// Parameter network must be "udp4".
-//
-// The timeout is used for connection setup, it doesn't affect the returned
-// connection. A timeout of 0 means infinite timeout.
-func (n *SCIONNetwork) ListenSCION(network string, laddr *Addr,
-	timeout time.Duration) (Conn, error) {
-
-	return n.ListenSCIONWithBindSVC(network, laddr, nil, addr.SvcNone, timeout)
-}
-
-// ListenSCIONWithBindSVC registers laddr with the dispatcher. Nil values for laddr are
+// Listen registers laddr with the dispatcher. Nil values for laddr are
 // not supported yet. The returned connection's ReadFrom and WriteTo methods
 // can be used to receive and send SCION packets with per-packet addressing.
 // Parameter network must be "udp4".
 //
 // The timeout is used for connection setup, it doesn't affect the returned
 // connection. A timeout of 0 means infinite timeout.
-func (n *SCIONNetwork) ListenSCIONWithBindSVC(network string, laddr, baddr *Addr,
+func (n *SCIONNetwork) Listen(network string, listen *net.UDPAddr,
 	svc addr.HostSVC, timeout time.Duration) (Conn, error) {
 
 	metrics.M.Listens().Inc()
@@ -160,69 +133,39 @@ func (n *SCIONNetwork) ListenSCIONWithBindSVC(network string, laddr, baddr *Addr
 	// normal operating system semantics for binding on 0.0.0.0 (it
 	// considers it to be a fixed address instead of a wildcard). To avoid
 	// misuse, disallow binding to nil or 0.0.0.0 addresses for now.
-	var l3Type addr.HostAddrType
 	switch network {
 	case "udp4":
-		l3Type = addr.HostTypeIPv4
 	default:
 		return nil, common.NewBasicError("Network not implemented", nil, "net", network)
 	}
-	if laddr == nil {
-		return nil, serrors.New("Nil laddr not supported")
-	}
-	if laddr.Host == nil {
-		return nil, serrors.New("Nil Host laddr not supported")
-	}
-	if laddr.Host.L3 == nil {
-		return nil, serrors.New("Nil Host L3 laddr not supported")
+	if listen == nil {
+		return nil, serrors.New("nil listen addr not supported")
 	}
-	if laddr.Host.L3.Type() != l3Type {
-		return nil, common.NewBasicError("Supplied local address does not match network", nil,
-			"expected L3", l3Type, "actual L3", laddr.Host.L3.Type())
+	if listen.IP == nil {
+		return nil, serrors.New("nil listen IP no supported")
 	}
-	if laddr.Host.L3.IP().IsUnspecified() {
-		return nil, serrors.New("Binding to unspecified address not supported")
+	if listen.IP.IsUnspecified() {
+		return nil, serrors.New("unspecified listen IP not supported")
 	}
 	conn := &scionConnBase{
 		net:      network,
 		scionNet: n,
 		svc:      svc,
-		laddr:    laddr.Copy(),
-	}
-	// Make sure the IA is set.
-	if conn.laddr.IA.IsZero() {
-		conn.laddr.IA = n.ia()
-	}
-	if !conn.laddr.IA.Equal(conn.scionNet.localIA) {
-		return nil, common.NewBasicError("Unable to listen on non-local IA", nil,
-			"expected", conn.scionNet.localIA, "actual", conn.laddr.IA, "type", "public")
-	}
-	var bindAddr *net.UDPAddr
-	if baddr != nil {
-		conn.baddr = baddr.Copy()
-		bindAddr = &net.UDPAddr{
-			IP:   baddr.Host.L3.IP(),
-			Port: int(baddr.Host.L4),
-		}
-		if !conn.baddr.IA.Equal(conn.scionNet.localIA) {
-			return nil, common.NewBasicError("Unable to listen on non-local IA", nil,
-				"expected", conn.scionNet.localIA, "actual", conn.baddr.IA, "type", "bind")
-		}
+		listen: &net.UDPAddr{
+			IP:   append(listen.IP[:0:0], listen.IP...),
+			Port: listen.Port,
+			Zone: listen.Zone,
+		},
 	}
-	p := conn.laddr.ToNetUDPAddr()
-	packetConn, port, err := conn.scionNet.dispatcher.RegisterTimeout(conn.laddr.IA,
-		p, bindAddr, svc, timeout)
+	packetConn, port, err := conn.scionNet.dispatcher.RegisterTimeout(n.localIA,
+		listen, nil, svc, timeout)
 	if err != nil {
 		return nil, err
 	}
-	if port != conn.laddr.Host.L4 {
+	if port != uint16(conn.listen.Port) {
 		// Update port
-		conn.laddr.Host.L4 = port
+		conn.listen.Port = int(port)
 	}
-	log.Debug("Registered with dispatcher", "addr", conn.laddr)
+	log.Debug("Registered with dispatcher", "addr", conn.listen)
 	return newSCIONConn(conn, n.querier, packetConn), nil
 }
-
-func (n *SCIONNetwork) ia() addr.IA {
-	return n.localIA
-}
diff --git a/go/lib/snet/squic/squic.go b/go/lib/snet/squic/squic.go
index 6bbda8c96..93683d027 100644
--- a/go/lib/snet/squic/squic.go
+++ b/go/lib/snet/squic/squic.go
@@ -1,4 +1,5 @@
 // Copyright 2017 ETH Zurich
+// Copyright 2019 ETH Zurich, Anapaya Systems
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -17,6 +18,7 @@ package squic
 
 import (
 	"crypto/tls"
+	"net"
 
 	"github.com/lucas-clemente/quic-go"
 
@@ -52,47 +54,36 @@ func Init(keyPath, pemPath string) error {
 	return nil
 }
 
-func DialSCION(network *snet.SCIONNetwork, laddr, raddr *snet.Addr,
-	quicConfig *quic.Config) (quic.Session, error) {
-
-	return DialSCIONWithBindSVC(network, laddr, raddr, nil, addr.SvcNone, quicConfig)
-}
-
-func DialSCIONWithBindSVC(network *snet.SCIONNetwork, laddr, raddr, baddr *snet.Addr,
+// Dial dials using quic over the scion network.
+func Dial(network *snet.SCIONNetwork, listen *net.UDPAddr, remote *snet.UDPAddr,
 	svc addr.HostSVC, quicConfig *quic.Config) (quic.Session, error) {
 
-	sconn, err := sListen(network, laddr, baddr, svc)
+	sconn, err := sListen(network, listen, svc)
 	if err != nil {
 		return nil, err
 	}
 	// Use dummy hostname, as it's used for SNI, and we're not doing cert verification.
-	return quic.Dial(sconn, raddr, "host:0", cliTlsCfg, quicConfig)
-}
-
-func ListenSCION(network *snet.SCIONNetwork, laddr *snet.Addr,
-	quicConfig *quic.Config) (quic.Listener, error) {
-
-	return ListenSCIONWithBindSVC(network, laddr, nil, addr.SvcNone, quicConfig)
+	return quic.Dial(sconn, remote, "host:0", cliTlsCfg, quicConfig)
 }
 
-func ListenSCIONWithBindSVC(network *snet.SCIONNetwork, laddr, baddr *snet.Addr,
+func Listen(network *snet.SCIONNetwork, listen *net.UDPAddr,
 	svc addr.HostSVC, quicConfig *quic.Config) (quic.Listener, error) {
 
 	if len(srvTlsCfg.Certificates) == 0 {
 		return nil, serrors.New("squic: No server TLS certificate configured")
 	}
-	sconn, err := sListen(network, laddr, baddr, svc)
+	sconn, err := sListen(network, listen, svc)
 	if err != nil {
 		return nil, err
 	}
 	return quic.Listen(sconn, srvTlsCfg, quicConfig)
 }
 
-func sListen(network *snet.SCIONNetwork, laddr, baddr *snet.Addr,
+func sListen(network *snet.SCIONNetwork, listen *net.UDPAddr,
 	svc addr.HostSVC) (snet.Conn, error) {
 
 	if network == nil {
 		return nil, serrors.New("squic:  SCION network must not be nil")
 	}
-	return network.ListenSCIONWithBindSVC("udp4", laddr, baddr, svc, 0)
+	return network.Listen("udp4", listen, svc, 0)
 }
diff --git a/go/lib/snet/writer.go b/go/lib/snet/writer.go
index 72ac90768..0418f42ba 100644
--- a/go/lib/snet/writer.go
+++ b/go/lib/snet/writer.go
@@ -64,7 +64,7 @@ func newScionConnWriter(base *scionConnBase, querier PathQuerier,
 		base: base,
 		conn: conn,
 		resolver: &remoteAddressResolver{
-			localIA:     base.laddr.IA,
+			localIA:     base.scionNet.localIA,
 			pathQuerier: querier,
 			monitor:     ctxmonitor.NewMonitor(),
 		},
@@ -98,7 +98,11 @@ func (c *scionConnWriter) Write(b []byte) (int, error) {
 }
 
 func (c *scionConnWriter) write(b []byte, raddr *Addr) (int, error) {
-	raddr, err := c.resolver.ResolveAddrPair(c.base.raddr, raddr)
+	var connRemote *Addr
+	if c.base.remote != nil {
+		connRemote = c.base.remote.ToAddr()
+	}
+	raddr, err := c.resolver.ResolveAddrPair(connRemote, raddr)
 	if err != nil {
 		return 0, err
 	}
@@ -112,10 +116,11 @@ func (c *scionConnWriter) writeWithLock(b []byte, raddr *Addr) (int, error) {
 		Bytes: Bytes(c.buffer),
 		SCIONPacketInfo: SCIONPacketInfo{
 			Destination: SCIONAddress{IA: raddr.IA, Host: raddr.Host.L3},
-			Source:      SCIONAddress{IA: c.base.laddr.IA, Host: c.base.laddr.Host.L3},
-			Path:        raddr.Path,
+			Source: SCIONAddress{IA: c.base.scionNet.localIA,
+				Host: addr.HostFromIP(c.base.listen.IP)},
+			Path: raddr.Path,
 			L4Header: &l4.UDP{
-				SrcPort:  c.base.laddr.Host.L4,
+				SrcPort:  uint16(c.base.listen.Port),
 				DstPort:  raddr.Host.L4,
 				TotalLen: uint16(l4.UDPLen + len(b)),
 			},
diff --git a/go/sig/egress/session/session.go b/go/sig/egress/session/session.go
index 0fc5bfa78..ded3c0284 100644
--- a/go/sig/egress/session/session.go
+++ b/go/sig/egress/session/session.go
@@ -20,6 +20,7 @@ package session
 import (
 	"context"
 	"fmt"
+	"net"
 	"sync/atomic"
 	"time"
 
@@ -75,8 +76,8 @@ func NewSession(dstIA addr.IA, sessId mgmt.SessionType, logger log.Logger,
 	s.healthy.Store(false)
 	s.ring = ringbuf.New(64, nil, fmt.Sprintf("egress_%s_%s", dstIA, sessId))
 	// Not using a fixed local port, as this is for outgoing data only.
-	s.conn, err = sigcmn.Network.ListenSCION("udp4",
-		&snet.Addr{IA: sigcmn.IA, Host: &addr.AppAddr{L3: sigcmn.Host}}, 0)
+	s.conn, err = sigcmn.Network.Listen("udp4",
+		&net.UDPAddr{IP: sigcmn.Host.IP()}, addr.SvcNone, 0)
 	s.sessMonStop = make(chan struct{})
 	s.sessMonStopped = make(chan struct{})
 	s.pktDispStop = make(chan struct{})
diff --git a/go/sig/internal/ingress/dispatcher.go b/go/sig/internal/ingress/dispatcher.go
index 45151becf..427076f84 100644
--- a/go/sig/internal/ingress/dispatcher.go
+++ b/go/sig/internal/ingress/dispatcher.go
@@ -60,7 +60,7 @@ func NewDispatcher(tio io.ReadWriteCloser) *Dispatcher {
 
 func (d *Dispatcher) Run() error {
 	var err error
-	d.extConn, err = sigcmn.Network.ListenSCION("udp4", d.laddr, 0)
+	d.extConn, err = sigcmn.Network.Listen("udp4", d.laddr.ToNetUDPAddr(), addr.SvcNone, 0)
 	if err != nil {
 		return common.NewBasicError("Unable to initialize extConn", err)
 	}
diff --git a/go/sig/sigcmn/common.go b/go/sig/sigcmn/common.go
index c93db37bb..e4230fc20 100644
--- a/go/sig/sigcmn/common.go
+++ b/go/sig/sigcmn/common.go
@@ -81,9 +81,8 @@ func Init(cfg sigconfig.SigConf, sdCfg env.SciondClient) error {
 	if err != nil {
 		return common.NewBasicError("Error creating local SCION Network context", err)
 	}
-	conn, err := network.ListenSCIONWithBindSVC("udp4",
-		&snet.Addr{IA: IA, Host: &addr.AppAddr{L3: Host, L4: cfg.CtrlPort}},
-		nil, addr.SvcSIG, 0)
+	conn, err := network.Listen("udp4",
+		&net.UDPAddr{IP: Host.IP(), Port: int(cfg.CtrlPort)}, addr.SvcSIG, 0)
 	if err != nil {
 		return common.NewBasicError("Error creating ctrl socket", err)
 	}


Test patch:
diff --git a/go/lib/snet/export_test.go b/go/lib/snet/export_test.go
index 4d47041f0..5de16c477 100644
--- a/go/lib/snet/export_test.go
+++ b/go/lib/snet/export_test.go
@@ -15,15 +15,18 @@
 package snet
 
 import (
+	"net"
+
 	"github.com/scionproto/scion/go/lib/addr"
 	"github.com/scionproto/scion/go/lib/snet/internal/ctxmonitor"
 )
 
 var NewScionConnWriter = newScionConnWriter
 
-func NewScionConnBase(laddr *Addr) *scionConnBase {
+func NewScionConnBase(localIA addr.IA, listen *net.UDPAddr) *scionConnBase {
 	return &scionConnBase{
-		laddr: laddr,
+		listen:   listen,
+		scionNet: &SCIONNetwork{localIA: localIA},
 	}
 }
 
diff --git a/go/lib/snet/writer_test.go b/go/lib/snet/writer_test.go
index 8c6e2706e..4a8db1396 100644
--- a/go/lib/snet/writer_test.go
+++ b/go/lib/snet/writer_test.go
@@ -184,7 +184,7 @@ func TestSetDeadline(t *testing.T) {
 	packetConn := snet.NewSCIONPacketConn(connMock, nil)
 
 	conn := snet.NewScionConnWriter(snet.NewScionConnBase(
-		MustParseAddr("2-ff00:0:1,[127.0.0.1]:80"),
+		xtest.MustParseIA("2-ff00:0:1"), MustParseUDPAddr("[127.0.0.1]:80"),
 	), querierMock, packetConn)
 	t.Run("And writes to multiple destinations for which path resolution is slow",
 		func(t *testing.T) {
@@ -212,3 +212,11 @@ func MustParseAddr(str string) *snet.Addr {
 	}
 	return address
 }
+
+func MustParseUDPAddr(ipPort string) *net.UDPAddr {
+	a, err := net.ResolveUDPAddr("udp", ipPort)
+	if err != nil {
+		panic(fmt.Sprintf("cannot resolve udp addr %s, %v", ipPort, err))
+	}
+	return a
+}