Index: uspace/srv/net/tl/tcp/pdu.c
===================================================================
--- uspace/srv/net/tl/tcp/pdu.c	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/pdu.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -48,7 +48,20 @@
 #define TCP_CHECKSUM_INIT 0xffff
 
+/** One's complement addition.
+ *
+ * Result is a + b + carry.
+ */
+static uint16_t tcp_ocadd16(uint16_t a, uint16_t b)
+{
+	uint32_t s;
+
+	s = (uint32_t)a + (uint32_t)b;
+	return (s & 0xffff) + (s >> 16);
+}
+
 static uint16_t tcp_checksum_calc(uint16_t ivalue, void *data, size_t size)
 {
 	uint16_t sum;
+	uint16_t w;
 	size_t words, i;
 	uint8_t *bdata;
@@ -59,9 +72,11 @@
 
 	for (i = 0; i < words; i++) {
-		sum += ~(((uint16_t)bdata[2*i] << 8) + bdata[2*i + 1]);
+		w = ((uint16_t)bdata[2*i] << 8) | bdata[2*i + 1];
+		sum = tcp_ocadd16(sum, w);
 	}
 
 	if (size % 2 != 0) {
-		sum += ~((uint16_t)bdata[2*words] << 8);
+		w = ((uint16_t)bdata[2*words] << 8);
+		sum = tcp_ocadd16(sum, w);
 	}
 
@@ -237,5 +252,5 @@
 
 	hdr = (tcp_header_t *)pdu->header;
-	hdr->checksum = host2uint16_t_le(checksum);
+	hdr->checksum = host2uint16_t_be(checksum);
 }
 
Index: uspace/srv/net/tl/tcp/sock.c
===================================================================
--- uspace/srv/net/tl/tcp/sock.c	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/sock.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -39,4 +39,5 @@
 #include <errno.h>
 #include <io/log.h>
+#include <ip_client.h>
 #include <ipc/socket.h>
 #include <net/modules.h>
@@ -106,4 +107,5 @@
 
 	sock->client = client;
+	sock->laddr.ipv4 = TCP_IPV4_ANY;
 
 	sock_id = SOCKET_GET_SOCKET_ID(call);
@@ -211,6 +213,9 @@
 	tcp_sockdata_t *socket;
 	tcp_error_t trc;
+	tcp_sock_t lsocket;
 	tcp_sock_t fsocket;
-	uint16_t lport;
+	device_id_t dev_id;
+	tcp_phdr_t *phdr;
+	size_t phdr_len;
 
 	log_msg(LVL_DEBUG, "tcp_sock_connect()");
@@ -243,9 +248,26 @@
 	}
 
-	lport = sock_core->port;
+	if (socket->laddr.ipv4 == TCP_IPV4_ANY) {
+		/* Find route to determine local IP address. */
+		rc = ip_get_route_req(ip_sess, IPPROTO_TCP,
+		    (struct sockaddr *)addr, sizeof(*addr), &dev_id,
+		    (void **)&phdr, &phdr_len);
+		if (rc != EOK) {
+			async_answer_0(callid, rc);
+			log_msg(LVL_DEBUG, "tcp_transmit_connect: Failed to find route.");
+			return;
+		}
+
+		socket->laddr.ipv4 = uint32_t_be2host(phdr->src_addr);
+		log_msg(LVL_DEBUG, "Local IP address is %x", socket->laddr.ipv4);
+		free(phdr);
+	}
+
+	lsocket.addr.ipv4 = socket->laddr.ipv4;
+	lsocket.port = sock_core->port;
 	fsocket.addr.ipv4 = uint32_t_be2host(addr->sin_addr.s_addr);
 	fsocket.port = uint16_t_be2host(addr->sin_port);
 
-	trc = tcp_uc_open(lport, &fsocket, ap_active, &socket->conn);
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_active, &socket->conn);
 
 	if (socket->conn != NULL)
@@ -280,4 +302,5 @@
 	tcp_sockdata_t *asocket;
 	tcp_error_t trc;
+	tcp_sock_t lsocket;
 	tcp_sock_t fsocket;
 	tcp_conn_t *conn;
@@ -305,8 +328,10 @@
 	log_msg(LVL_DEBUG, " - open connection");
 
+	lsocket.addr.ipv4 = TCP_IPV4_ANY;
+	lsocket.port = sock_core->port;
 	fsocket.addr.ipv4 = TCP_IPV4_ANY;
 	fsocket.port = TCP_PORT_ANY;
 
-	trc = tcp_uc_open(sock_core->port, &fsocket, ap_passive, &conn);
+	trc = tcp_uc_open(&lsocket, &fsocket, ap_passive, &conn);
 	if (conn != NULL)
 		conn->name = (char *)"S";
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -64,5 +64,5 @@
 async_sess_t *net_sess;
 static async_sess_t *icmp_sess;
-static async_sess_t *ip_sess;
+async_sess_t *ip_sess;
 packet_dimensions_t pkt_dims;
 
Index: uspace/srv/net/tl/tcp/tcp.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp.h	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/tcp.h	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -41,4 +41,5 @@
 
 extern async_sess_t *net_sess;
+extern async_sess_t *ip_sess;
 extern void tcp_transmit_pdu(tcp_pdu_t *);
 
Index: uspace/srv/net/tl/tcp/tcp_type.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_type.h	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/tcp_type.h	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -304,6 +304,10 @@
 
 typedef struct {
+	/** Client */
 	tcp_client_t *client;
+	/** Connection */
 	tcp_conn_t *conn;
+	/** Local address */
+	netaddr_t laddr;
 } tcp_sockdata_t;
 
Index: uspace/srv/net/tl/tcp/test.c
===================================================================
--- uspace/srv/net/tl/tcp/test.c	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/test.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -50,5 +50,6 @@
 {
 	tcp_conn_t *conn;
-	tcp_sock_t sock;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
 	char rcv_buf[RCV_BUF_SIZE + 1];
 	size_t rcvd;
@@ -56,8 +57,10 @@
 
 	printf("test_srv()\n");
-	sock.port = 1024;
-	sock.addr.ipv4 = 0x7f000001;
+	lsock.port = 80;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 1024;
+	fsock.addr.ipv4 = 0x7f000001;
 	printf("S: User open...\n");
-	tcp_uc_open(80, &sock, ap_passive, &conn);
+	tcp_uc_open(&lsock, &fsock, ap_passive, &conn);
 	conn->name = (char *) "S";
 
@@ -86,15 +89,18 @@
 {
 	tcp_conn_t *conn;
-	tcp_sock_t sock;
+	tcp_sock_t lsock;
+	tcp_sock_t fsock;
 	const char *msg = "Hello World!";
 
 	printf("test_cli()\n");
 
-	sock.port = 80;
-	sock.addr.ipv4 = 0x7f000001;
+	lsock.port = 1024;
+	lsock.addr.ipv4 = 0x7f000001;
+	fsock.port = 80;
+	fsock.addr.ipv4 = 0x7f000001;
 
 	async_usleep(1000*1000*3);
 	printf("C: User open...\n");
-	tcp_uc_open(1024, &sock, ap_active, &conn);
+	tcp_uc_open(&lsock, &fsock, ap_active, &conn);
 	conn->name = (char *) "C";
 
Index: uspace/srv/net/tl/tcp/ucall.c
===================================================================
--- uspace/srv/net/tl/tcp/ucall.c	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/ucall.c	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -50,8 +50,12 @@
 /** OPEN user call
  *
- * @param lport		Local port
+ * @param lsock		Local socket
  * @param fsock		Foreign socket
  * @param acpass	Active/passive
  * @param conn		Connection
+ *
+ * Unlike in the spec we allow specifying the local address. This means
+ * the implementation does not need to magically guess it, especially
+ * considering there can be more than one local address.
  *
  * XXX We should be able to call active open on an existing listening
@@ -60,18 +64,14 @@
  * establishment.
  */
-tcp_error_t tcp_uc_open(uint16_t lport, tcp_sock_t *fsock, acpass_t acpass,
+tcp_error_t tcp_uc_open(tcp_sock_t *lsock, tcp_sock_t *fsock, acpass_t acpass,
     tcp_conn_t **conn)
 {
 	tcp_conn_t *nconn;
-	tcp_sock_t lsock;
-
-	log_msg(LVL_DEBUG, "tcp_uc_open(%" PRIu16 ", %p, %s, %p)",
-	    lport, fsock, acpass == ap_active ? "active" : "passive",
+
+	log_msg(LVL_DEBUG, "tcp_uc_open(%p, %p, %s, %p)",
+	    lsock, fsock, acpass == ap_active ? "active" : "passive",
 	    conn);
 
-	lsock.port = lport;
-	lsock.addr.ipv4 = TCP_IPV4_ANY;
-
-	nconn = tcp_conn_new(&lsock, fsock);
+	nconn = tcp_conn_new(lsock, fsock);
 	tcp_conn_add(nconn);
 
@@ -246,4 +246,6 @@
 		if (conn->ident.foreign.port == TCP_PORT_ANY)
 			conn->ident.foreign.port = sp->foreign.port;
+		if (conn->ident.local.addr.ipv4 == TCP_IPV4_ANY)
+			conn->ident.local.addr.ipv4 = sp->local.addr.ipv4;
 
 		tcp_conn_segment_arrived(conn, seg);
Index: uspace/srv/net/tl/tcp/ucall.h
===================================================================
--- uspace/srv/net/tl/tcp/ucall.h	(revision 5f9ecd34daa4f458c7b11e35f9997672a4507752)
+++ uspace/srv/net/tl/tcp/ucall.h	(revision 0ac215896a5381e04f091bb4999140a0e38f21a3)
@@ -42,5 +42,5 @@
  * User calls
  */
-extern tcp_error_t tcp_uc_open(uint16_t, tcp_sock_t *, acpass_t, tcp_conn_t **);
+extern tcp_error_t tcp_uc_open(tcp_sock_t *, tcp_sock_t *, acpass_t, tcp_conn_t **);
 extern tcp_error_t tcp_uc_send(tcp_conn_t *, void *, size_t, xflags_t);
 extern tcp_error_t tcp_uc_receive(tcp_conn_t *, void *, size_t, size_t *, xflags_t *);
