Index: uspace/srv/net/il/ip/ip.c
===================================================================
--- uspace/srv/net/il/ip/ip.c	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/net/il/ip/ip.c	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -201,5 +201,5 @@
 
 	/* Set the destination address */
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(dest_in);
@@ -635,5 +635,5 @@
 
 	/* Process all IP options */
-	while (next < first->header_length) {
+	while (next < GET_IP_HEADER_LENGTH(first)) {
 		option = (ip_option_t *) (((uint8_t *) first) + next);
 		/* Skip end or noop */
@@ -656,7 +656,7 @@
 	if (length % 4) {
 		bzero(((uint8_t *) last) + length, 4 - (length % 4));
-		last->header_length = length / 4 + 1;
+		SET_IP_HEADER_LENGTH(last, (length / 4 + 1));
 	} else {
-		last->header_length = length / 4;
+		SET_IP_HEADER_LENGTH(last, (length / 4));
 	}
 
@@ -706,6 +706,6 @@
 		return rc;
 	
-	header->version = IPV4;
-	header->fragment_offset_high = 0;
+	SET_IP_HEADER_VERSION(header, IPV4);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(header, 0);
 	header->fragment_offset_low = 0;
 	header->header_checksum = 0;
@@ -735,9 +735,10 @@
 			memcpy(middle_header, last_header,
 			    IP_HEADER_LENGTH(last_header));
-			header->flags |= IPFLAG_MORE_FRAGMENTS;
+			SET_IP_HEADER_FLAGS(header,
+			    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 			middle_header->total_length =
 			    htons(packet_get_data_length(next));
-			middle_header->fragment_offset_high =
-			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+			SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+			    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 			middle_header->fragment_offset_low =
 			    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -768,6 +769,6 @@
 		middle_header->total_length =
 		    htons(packet_get_data_length(next));
-		middle_header->fragment_offset_high =
-		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length);
+		SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(middle_header,
+		    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(length));
 		middle_header->fragment_offset_low =
 		    IP_COMPUTE_FRAGMENT_OFFSET_LOW(length);
@@ -785,5 +786,6 @@
 		length += packet_get_data_length(next);
 		free(last_header);
-		header->flags |= IPFLAG_MORE_FRAGMENTS;
+		SET_IP_HEADER_FLAGS(header,
+		    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 	}
 
@@ -834,6 +836,6 @@
 	new_header->total_length = htons(IP_HEADER_LENGTH(new_header) + length);
 	offset = IP_FRAGMENT_OFFSET(header) + IP_HEADER_DATA_LENGTH(header);
-	new_header->fragment_offset_high =
-	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset);
+	SET_IP_HEADER_FRAGMENT_OFFSET_HIGH(new_header,
+	    IP_COMPUTE_FRAGMENT_OFFSET_HIGH(offset));
 	new_header->fragment_offset_low =
 	    IP_COMPUTE_FRAGMENT_OFFSET_LOW(offset);
@@ -865,5 +867,6 @@
 		return NULL;
 	memcpy(middle, last, IP_HEADER_LENGTH(last));
-	middle->flags |= IPFLAG_MORE_FRAGMENTS;
+	SET_IP_HEADER_FLAGS(middle,
+	    (GET_IP_HEADER_FLAGS(middle) | IPFLAG_MORE_FRAGMENTS));
 	return middle;
 }
@@ -922,5 +925,5 @@
 
 	/* Fragmentation forbidden? */
-	if(header->flags & IPFLAG_DONT_FRAGMENT)
+	if(GET_IP_HEADER_FLAGS(header) & IPFLAG_DONT_FRAGMENT)
 		return EPERM;
 
@@ -958,5 +961,6 @@
 
 	/* Mark the first as fragmented */
-	header->flags |= IPFLAG_MORE_FRAGMENTS;
+	SET_IP_HEADER_FLAGS(header,
+	    (GET_IP_HEADER_FLAGS(header) | IPFLAG_MORE_FRAGMENTS));
 
 	/* Create middle fragments */
@@ -1319,5 +1323,5 @@
 	int rc;
 
-	if ((header->flags & IPFLAG_MORE_FRAGMENTS) ||
+	if ((GET_IP_HEADER_FLAGS(header) & IPFLAG_MORE_FRAGMENTS) ||
 	    IP_FRAGMENT_OFFSET(header)) {
 		// TODO fragmented
@@ -1325,5 +1329,5 @@
 	}
 	
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(src_in);
@@ -1447,5 +1451,5 @@
 
 	/* Set the destination address */
-	switch (header->version) {
+	switch (GET_IP_HEADER_VERSION(header)) {
 	case IPVERSION:
 		addrlen = sizeof(addr_in);
Index: uspace/srv/net/tl/tcp/tcp.c
===================================================================
--- uspace/srv/net/tl/tcp/tcp.c	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/net/tl/tcp/tcp.c	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -476,5 +476,5 @@
 	old_incoming = socket_data->next_incoming;
 
-	if (header->finalize) {
+	if (GET_TCP_HEADER_FINALIZE(header)) {
 		socket_data->fin_incoming = new_sequence_number +
 		    total_length - TCP_HEADER_LENGTH(header);
@@ -838,5 +838,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 	
@@ -903,5 +903,5 @@
 	assert(packet);
 
-	if (!header->synchronize)
+	if (!GET_TCP_HEADER_SYNCHRONIZE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -1057,5 +1057,5 @@
 	assert(packet);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return tcp_release_and_return(packet, EINVAL);
 
@@ -1126,5 +1126,5 @@
 	assert(header);
 
-	if (!header->acknowledge)
+	if (!GET_TCP_HEADER_ACKNOWLEDGE(header))
 		return;
 
@@ -1833,5 +1833,5 @@
 
 	/* Remember the outgoing FIN */
-	if (header->finalize) 
+	if (GET_TCP_HEADER_FINALIZE(header))
 		socket_data->fin_outgoing = socket_data->next_outgoing;
 	
@@ -1952,5 +1952,5 @@
 		header->acknowledgement_number =
 		    htonl(socket_data->next_incoming);
-		header->acknowledge = 1;
+		SET_TCP_HEADER_ACKNOWLEDGE(header, 1);
 	}
 	header->window = htons(socket_data->window);
@@ -2024,7 +2024,8 @@
 	header->source_port = htons(socket->port);
 	header->source_port = htons(socket_data->dest_port);
-	header->header_length = TCP_COMPUTE_HEADER_LENGTH(sizeof(*header));
-	header->synchronize = synchronize;
-	header->finalize = finalize;
+	SET_TCP_HEADER_LENGTH(header,
+	    TCP_COMPUTE_HEADER_LENGTH(sizeof(*header)));
+	SET_TCP_HEADER_SYNCHRONIZE(header, synchronize);
+	SET_TCP_HEADER_FINALIZE(header, finalize);
 }
 
Index: uspace/srv/net/tl/tcp/tcp_header.h
===================================================================
--- uspace/srv/net/tl/tcp/tcp_header.h	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/net/tl/tcp/tcp_header.h	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -47,5 +47,5 @@
  * @param[in] header The TCP packet header.
  */
-#define TCP_HEADER_LENGTH(header)		((header)->header_length * 4U)
+#define TCP_HEADER_LENGTH(header)		(GET_TCP_HEADER_LENGTH(header) * 4U)
 
 /** Returns the TCP header length.
@@ -73,30 +73,63 @@
 	uint32_t sequence_number;
 	uint32_t acknowledgement_number;
-	
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t header_length:4;
-	uint8_t reserved1:4;
-#else
-	uint8_t reserved1:4;
-	uint8_t header_length:4;
-#endif
 
-#ifdef ARCH_IS_BIG_ENDIAN
-	uint8_t reserved2:2;
-	uint8_t urgent:1;
-	uint8_t acknowledge:1;
-	uint8_t push:1;
-	uint8_t reset:1;
-	uint8_t synchronize:1;
-	uint8_t finalize:1;
-#else
-	uint8_t finalize:1;
-	uint8_t synchronize:1;
-	uint8_t reset:1;
-	uint8_t push:1;
-	uint8_t acknowledge:1;
-	uint8_t urgent:1;
-	uint8_t reserved2:2;
-#endif
+	uint8_t hlr; /* header length, reserved1 */
+
+#define GET_TCP_HEADER_LENGTH(header) \
+	(((header)->hlr & 0xf0) >> 4)
+#define SET_TCP_HEADER_LENGTH(header, length) \
+	((header)->hlr = \
+	 ((length & 0x0f) << 4) | ((header)->hlr & 0x0f))
+
+#define GET_TCP_HEADER_RESERVED1(header) \
+	((header)->hlr & 0x0f)
+#define SET_TCP_HEADER_RESERVED1(header, reserved1) \
+	((header)->hlr = \
+	 (reserved1 & 0x0f) | ((header)->hlr & 0xf0))
+
+	/* reserved2, urgent, acknowledge, push, reset, synchronize, finalize */
+	uint8_t ruaprsf;  
+
+#define GET_TCP_HEADER_RESERVED2(header) \
+	(((header)->ruaprsf & 0xc0) >> 6)
+#define SET_TCP_HEADER_RESERVED2(header, reserved2) \
+	((header)->ruaprsf = \
+	 ((reserved2 & 0x03) << 6) | ((header)->ruaprsf & 0x3f))
+
+#define GET_TCP_HEADER_URGENT(header) \
+	(((header)->ruaprsf & 0x20) >> 5)
+#define SET_TCP_HEADER_URGENT(header, urgent) \
+	((header)->ruaprsf = \
+	 ((urgent & 0x01) << 5) | ((header)->ruaprsf & 0xdf))
+
+#define GET_TCP_HEADER_ACKNOWLEDGE(header) \
+	(((header)->ruaprsf & 0x10) >> 4)
+#define SET_TCP_HEADER_ACKNOWLEDGE(header, acknowledge) \
+	((header)->ruaprsf = \
+	 ((acknowledge & 0x01) << 4) | ((header)->ruaprsf & 0xef))
+
+#define GET_TCP_HEADER_PUSH(header) \
+	(((header)->ruaprsf & 0x08) >> 3)
+#define SET_TCP_HEADER_PUSH(header, push) \
+	((header)->ruaprsf = \
+	 ((push & 0x01) << 3) | ((header)->ruaprsf & 0xf7))
+
+#define GET_TCP_HEADER_RESET(header) \
+	(((header)->ruaprsf & 0x04) >> 2)
+#define SET_TCP_HEADER_RESET(header, reset) \
+	((header)->ruaprsf = \
+	 ((reset & 0x01) << 2) | ((header)->ruaprsf & 0xfb))
+
+#define GET_TCP_HEADER_SYNCHRONIZE(header) \
+	(((header)->ruaprsf & 0x02) >> 1)
+#define SET_TCP_HEADER_SYNCHRONIZE(header, synchronize) \
+	((header)->ruaprsf = \
+	 ((synchronize & 0x01) << 1) | ((header)->ruaprsf & 0xfd))
+
+#define GET_TCP_HEADER_FINALIZE(header) \
+	((header)->ruaprsf & 0x01)
+#define SET_TCP_HEADER_FINALIZE(header, finalize) \
+	((header)->ruaprsf = \
+	 (finalize & 0x01) | ((header)->ruaprsf & 0xfe))
 
 	uint16_t window;
Index: uspace/srv/vfs/vfs.h
===================================================================
--- uspace/srv/vfs/vfs.h	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/vfs/vfs.h	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -176,5 +176,4 @@
     vfs_pair_t *, ...);
 extern int vfs_open_node_internal(vfs_lookup_res_t *);
-extern int vfs_close_internal(vfs_file_t *);
 
 extern bool vfs_nodes_init(void);
Index: uspace/srv/vfs/vfs_file.c
===================================================================
--- uspace/srv/vfs/vfs_file.c	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/vfs/vfs_file.c	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -79,5 +79,4 @@
 	for (i = 0; i < MAX_OPEN_FILES; i++) {
 		if (FILES[i]) {
-			(void) vfs_close_internal(FILES[i]);
 			(void) vfs_fd_free(i);
 		}
@@ -108,4 +107,24 @@
 }
 
+/** Close the file in the endpoint FS server. */
+static int vfs_file_close_remote(vfs_file_t *file)
+{
+	ipc_call_t answer;
+	aid_t msg;
+	sysarg_t rc;
+	int phone;
+
+	assert(!file->refcnt);
+
+	phone = vfs_grab_phone(file->node->fs_handle);
+	msg = async_send_2(phone, VFS_OUT_CLOSE, file->node->devmap_handle,
+	    file->node->index, &answer);
+	async_wait_for(msg, &rc);
+	vfs_release_phone(file->node->fs_handle, phone);
+
+	return IPC_GET_ARG1(answer);
+}
+
+
 /** Increment reference count of VFS file structure.
  *
@@ -125,16 +144,21 @@
  *			decremented.
  */
-static void vfs_file_delref(vfs_file_t *file)
-{
+static int vfs_file_delref(vfs_file_t *file)
+{
+	int rc = EOK;
+
 	assert(fibril_mutex_is_locked(&VFS_DATA->lock));
 
 	if (file->refcnt-- == 1) {
 		/*
-		 * Lost the last reference to a file, need to drop our reference
-		 * to the underlying VFS node.
+		 * Lost the last reference to a file, need to close it in the
+		 * endpoint FS and drop our reference to the underlying VFS node.
 		 */
+		rc = vfs_file_close_remote(file);
 		vfs_node_delref(file->node);
 		free(file);
 	}
+
+	return rc;
 }
 
@@ -201,4 +225,6 @@
 int vfs_fd_free(int fd)
 {
+	int rc;
+
 	if (!vfs_files_init())
 		return ENOMEM;
@@ -210,9 +236,9 @@
 	}
 	
-	vfs_file_delref(FILES[fd]);
+	rc = vfs_file_delref(FILES[fd]);
 	FILES[fd] = NULL;
 	fibril_mutex_unlock(&VFS_DATA->lock);
 	
-	return EOK;
+	return rc;
 }
 
Index: uspace/srv/vfs/vfs_ops.c
===================================================================
--- uspace/srv/vfs/vfs_ops.c	(revision 1a86c50774ee47210dbe00882e1be08f29c4c5cd)
+++ uspace/srv/vfs/vfs_ops.c	(revision 6a7e497a7d1685485756693cc42f76f38039ad44)
@@ -717,55 +717,9 @@
 }
 
-int vfs_close_internal(vfs_file_t *file)
-{
-	/*
-	 * Lock the open file structure so that no other thread can manipulate
-	 * the same open file at a time.
-	 */
-	fibril_mutex_lock(&file->lock);
-	
-	if (file->refcnt <= 1) {
-		/* Only close the file on the destination FS server
-		   if there are no more file descriptors (except the
-		   present one) pointing to this file. */
-		
-		int fs_phone = vfs_grab_phone(file->node->fs_handle);
-		
-		/* Make a VFS_OUT_CLOSE request at the destination FS server. */
-		aid_t msg;
-		ipc_call_t answer;
-		msg = async_send_2(fs_phone, VFS_OUT_CLOSE,
-		    file->node->devmap_handle, file->node->index, &answer);
-		
-		/* Wait for reply from the FS server. */
-		sysarg_t rc;
-		async_wait_for(msg, &rc);
-		
-		vfs_release_phone(file->node->fs_handle, fs_phone);
-		fibril_mutex_unlock(&file->lock);
-		
-		return IPC_GET_ARG1(answer);
-	}
-	
-	fibril_mutex_unlock(&file->lock);
-	return EOK;
-}
-
 void vfs_close(ipc_callid_t rid, ipc_call_t *request)
 {
 	int fd = IPC_GET_ARG1(*request);
-	
-	/* Lookup the file structure corresponding to the file descriptor. */
-	vfs_file_t *file = vfs_file_get(fd);
-	if (!file) {
-		async_answer_0(rid, ENOENT);
-		return;
-	}
-	
-	int ret = vfs_close_internal(file);
-	if (ret != EOK)
-		async_answer_0(rid, ret);
-	
-	vfs_file_put(file);
+	int ret;
+	
 	ret = vfs_fd_free(fd);
 	async_answer_0(rid, ret);
@@ -1369,27 +1323,6 @@
 	fibril_mutex_lock(&oldfile->lock);
 	
-	/* Lookup an open file structure possibly corresponding to newfd. */
-	vfs_file_t *newfile = vfs_file_get(newfd);
-	if (newfile) {
-		/* Close the originally opened file. */
-		int ret = vfs_close_internal(newfile);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		
-		ret = vfs_fd_free(newfd);
-		if (ret != EOK) {
-			fibril_mutex_unlock(&oldfile->lock);
-			vfs_file_put(oldfile);
-			vfs_file_put(newfile);
-			async_answer_0(rid, ret);
-			return;
-		}
-		vfs_file_put(newfile);
-	}
+	/* Make sure newfd is closed. */
+	(void) vfs_fd_free(newfd);
 	
 	/* Assign the old file to newfd. */
