diff --git a/fs/ceph/decode.h b/fs/ceph/decode.h
index 91179fb2cc3fd7a6a9f07ecc80b1638ebf5a3a4b..a382aecc55bb3cd95b7aedf6e37df269a84b1711 100644
--- a/fs/ceph/decode.h
+++ b/fs/ceph/decode.h
@@ -76,18 +76,30 @@ static inline void ceph_decode_copy(void **p, void *pv, size_t n)
  * struct ceph_timespec <-> struct timespec
  */
 static inline void ceph_decode_timespec(struct timespec *ts,
-					struct ceph_timespec *tv)
+					const struct ceph_timespec *tv)
 {
 	ts->tv_sec = le32_to_cpu(tv->tv_sec);
 	ts->tv_nsec = le32_to_cpu(tv->tv_nsec);
 }
 static inline void ceph_encode_timespec(struct ceph_timespec *tv,
-					struct timespec *ts)
+					const struct timespec *ts)
 {
 	tv->tv_sec = cpu_to_le32(ts->tv_sec);
 	tv->tv_nsec = cpu_to_le32(ts->tv_nsec);
 }
 
+/*
+ * sockaddr_storage <-> ceph_sockaddr
+ */
+static inline void ceph_encode_addr(struct ceph_entity_addr *a)
+{
+	a->in_addr.ss_family = htons(a->in_addr.ss_family);
+}
+static inline void ceph_decode_addr(struct ceph_entity_addr *a)
+{
+	a->in_addr.ss_family = ntohs(a->in_addr.ss_family);
+}
+
 /*
  * encoders
  */
diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c
index 80daea0644707db640a352421adc73b884b8cce5..4226c810ce2257cf8ca5800eb3f8456be3dd6d1c 100644
--- a/fs/ceph/mdsmap.c
+++ b/fs/ceph/mdsmap.c
@@ -86,6 +86,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end)
 
 		ceph_decode_need(p, end, sizeof(addr) + 1 + sizeof(u32), bad);
 		ceph_decode_copy(p, &addr, sizeof(addr));
+		ceph_decode_addr(&addr);
 		infoversion = ceph_decode_8(p);
 		namelen = ceph_decode_32(p);  /* skip mds name */
 		*p += namelen;
diff --git a/fs/ceph/messenger.c b/fs/ceph/messenger.c
index b48abc0b3be7f8aee438de2e02a46957f75378c7..6ff44bbddf67f36d081a413f8695e2dc73a53548 100644
--- a/fs/ceph/messenger.c
+++ b/fs/ceph/messenger.c
@@ -12,6 +12,7 @@
 
 #include "super.h"
 #include "messenger.h"
+#include "decode.h"
 
 /*
  * Ceph uses the messenger to exchange ceph_msg messages with other
@@ -97,6 +98,12 @@ const char *pr_addr(const struct sockaddr_storage *ss)
 	return s;
 }
 
+static void encode_my_addr(struct ceph_messenger *msgr)
+{
+	memcpy(&msgr->my_enc_addr, &msgr->inst.addr, sizeof(msgr->my_enc_addr));
+	ceph_encode_addr(&msgr->my_enc_addr);
+}
+
 /*
  * work queue for all reading and writing to/from the socket.
  */
@@ -590,12 +597,12 @@ static void prepare_write_connect(struct ceph_messenger *msgr,
 
 	con->out_kvec[0].iov_base = CEPH_BANNER;
 	con->out_kvec[0].iov_len = len;
-	con->out_kvec[1].iov_base = &msgr->inst.addr;
-	con->out_kvec[1].iov_len = sizeof(msgr->inst.addr);
+	con->out_kvec[1].iov_base = &msgr->my_enc_addr;
+	con->out_kvec[1].iov_len = sizeof(msgr->my_enc_addr);
 	con->out_kvec[2].iov_base = &con->out_connect;
 	con->out_kvec[2].iov_len = sizeof(con->out_connect);
 	con->out_kvec_left = 3;
-	con->out_kvec_bytes = len + sizeof(msgr->inst.addr) +
+	con->out_kvec_bytes = len + sizeof(msgr->my_enc_addr) +
 		sizeof(con->out_connect);
 	con->out_kvec_cur = con->out_kvec;
 	con->out_more = 0;
@@ -976,6 +983,9 @@ static int process_connect(struct ceph_connection *con)
 	if (verify_hello(con) < 0)
 		return -1;
 
+	ceph_decode_addr(&con->actual_peer_addr);
+	ceph_decode_addr(&con->peer_addr_for_me);
+
 	/*
 	 * Make sure the other end is who we wanted.  note that the other
 	 * end may not yet know their ip address, so if it's 0.0.0.0, give
@@ -1005,6 +1015,7 @@ static int process_connect(struct ceph_connection *con)
 		       &con->peer_addr_for_me.in_addr,
 		       sizeof(con->peer_addr_for_me.in_addr));
 		addr_set_port(&con->msgr->inst.addr.in_addr, port);
+		encode_my_addr(con->msgr);
 		dout("process_connect learned my addr is %s\n",
 		     pr_addr(&con->msgr->inst.addr.in_addr));
 	}
@@ -1780,6 +1791,7 @@ struct ceph_messenger *ceph_messenger_create(struct ceph_entity_addr *myaddr)
 	/* select a random nonce */
 	get_random_bytes(&msgr->inst.addr.nonce,
 			 sizeof(msgr->inst.addr.nonce));
+	encode_my_addr(msgr);
 
 	dout("messenger_create %p\n", msgr);
 	return msgr;
@@ -1806,8 +1818,9 @@ void ceph_con_send(struct ceph_connection *con, struct ceph_msg *msg)
 	}
 
 	/* set src+dst */
-	msg->hdr.src = con->msgr->inst;
-	msg->hdr.orig_src = con->msgr->inst;
+	msg->hdr.src.name = con->msgr->inst.name;
+	msg->hdr.src.addr = con->msgr->my_enc_addr;
+	msg->hdr.orig_src = msg->hdr.src;
 	msg->hdr.dst_erank = con->peer_addr.erank;
 
 	/* queue */
diff --git a/fs/ceph/messenger.h b/fs/ceph/messenger.h
index dcd98b64dca97d44a04694fc4c90fcd9f9d40ad2..e016fa7cf970ae9e3b9e0410e2b76a7212ef5952 100644
--- a/fs/ceph/messenger.h
+++ b/fs/ceph/messenger.h
@@ -53,6 +53,7 @@ extern const char *ceph_name_type_str(int t);
 
 struct ceph_messenger {
 	struct ceph_entity_inst inst;    /* my name+address */
+	struct ceph_entity_addr my_enc_addr;
 	struct page *zero_page;          /* used in certain error cases */
 
 	bool nocrc;
diff --git a/fs/ceph/mon_client.c b/fs/ceph/mon_client.c
index 61263c99c6a809b542da0c7dde189eca29c4afca..95b76e761e1828a1cd0e9740a2f02aef14fd254d 100644
--- a/fs/ceph/mon_client.c
+++ b/fs/ceph/mon_client.c
@@ -59,6 +59,8 @@ struct ceph_monmap *ceph_monmap_decode(void *p, void *end)
 	m->epoch = epoch;
 	m->num_mon = num_mon;
 	ceph_decode_copy(&p, m->mon_inst, num_mon*sizeof(m->mon_inst[0]));
+	for (i = 0; i < num_mon; i++)
+		ceph_decode_addr(&m->mon_inst[i].addr);
 
 	dout("monmap_decode epoch %d, num_mon %d\n", m->epoch,
 	     m->num_mon);
diff --git a/fs/ceph/msgr.h b/fs/ceph/msgr.h
index 9abc879e25b1b3f3f3b27c5000a6abaaac5523d0..8e3ea2eb1bf512e6cdee0dee1dd91f892658dc1c 100644
--- a/fs/ceph/msgr.h
+++ b/fs/ceph/msgr.h
@@ -21,7 +21,7 @@
  * whenever the wire protocol changes.  try to keep this string length
  * constant.
  */
-#define CEPH_BANNER "ceph v022"
+#define CEPH_BANNER "ceph v023"
 #define CEPH_BANNER_MAX_LEN 30
 
 
diff --git a/fs/ceph/osdmap.c b/fs/ceph/osdmap.c
index d62e111b8a342f3a4127238e113e01561fcafaa6..cd7bb265d7892c9b5d6a868b34fae72ae5a886ab 100644
--- a/fs/ceph/osdmap.c
+++ b/fs/ceph/osdmap.c
@@ -460,6 +460,8 @@ struct ceph_osdmap *osdmap_decode(void **p, void *end)
 
 	*p += 4; /* skip length field (should match max) */
 	ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr));
+	for (i = 0; i < map->max_osd; i++)
+		ceph_decode_addr(&map->osd_addr[i]);
 
 	/* pg_temp */
 	ceph_decode_32_safe(p, end, len, bad);
@@ -619,6 +621,7 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end,
 		struct ceph_entity_addr addr;
 		ceph_decode_32_safe(p, end, osd, bad);
 		ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad);
+		ceph_decode_addr(&addr);
 		pr_info("osd%d up\n", osd);
 		BUG_ON(osd >= map->max_osd);
 		map->osd_state[osd] |= CEPH_OSD_UP;