tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

sctp & ipv4-mapped ipv6 fix



hi,

the attached patch converts sctp to use in6_sin_2_v4mapsin6().

it was kept separate from the previous patch posted since the existing
sctp code seems to be building the mapped address incorrectly.

(hoping to get confirmation here)

the existing code seems to set the incorrect parts of the sin6.sin6_addr
structure (uses the wrong s6_addr offsets).

(1) s6_addr16[2] = 0xffff
(2) bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
        sizeof(sin6.sin6_addr.s6_addr16[3]));

using in6_sin_2_v4mapsin6() should resolve this.

rtr
Index: netinet/sctp_indata.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/sctp_indata.c,v
retrieving revision 1.2
diff -p -u -U 8 -r1.2 sctp_indata.c
--- netinet/sctp_indata.c	13 Dec 2015 18:53:57 -0000	1.2
+++ netinet/sctp_indata.c	15 Feb 2016 15:10:21 -0000
@@ -419,23 +419,17 @@ sctp_deliver_data(struct sctp_tcb *stcb,
 
 		control = sctp_build_ctl(stcb, chk);
 		to = rtcache_getdst(&chk->whoTo->ro);
 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 		    to->sa_family == AF_INET) {
 			const struct sockaddr_in *sin;
 
 			sin = (const struct sockaddr_in *)to;
-			memset(&sin6, 0, sizeof(sin6));
-			sin6.sin6_family = AF_INET6;
-			sin6.sin6_len = sizeof(struct sockaddr_in6);
-			sin6.sin6_addr.s6_addr16[2] = 0xffff;
-			bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-			    sizeof(sin6.sin6_addr.s6_addr16[3]));
-			sin6.sin6_port = sin->sin_port;
+			in6_sin_2_v4mapsin6(sin, &sin6);
 			to = (struct sockaddr *)&sin6;
 		}
 		/* check and strip embedded scope junk */
 		to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 		    &lsa6);
 		if (((const struct sockaddr_in *)to)->sin_port == 0) {
 			printf("Huh a, port is %d not net:%p %d?\n",
 			       ((const struct sockaddr_in *)to)->sin_port,
@@ -648,24 +642,17 @@ sctp_service_reassembly(struct sctp_tcb 
 
 			control = sctp_build_ctl(stcb, chk);
 			to = rtcache_getdst(&chk->whoTo->ro);
 			if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 			    to->sa_family == AF_INET) {
 				const struct sockaddr_in *sin;
 
 				sin = satocsin(to);
-				memset(&sin6, 0, sizeof(sin6));
-				sin6.sin6_family = AF_INET6;
-				sin6.sin6_len = sizeof(struct sockaddr_in6);
-				sin6.sin6_addr.s6_addr16[2] = 0xffff;
-				bcopy(&sin->sin_addr,
-				      &sin6.sin6_addr.s6_addr16[3],
-				      sizeof(sin6.sin6_addr.s6_addr16[3]));
-				sin6.sin6_port = sin->sin_port;
+				in6_sin_2_v4mapsin6(sin, &sin6);
 				to = (struct sockaddr *)&sin6;
 			}
 			/* check and strip embedded scope junk */
 			to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 								   &lsa6);
 			if (((const struct sockaddr_in *)to)->sin_port == 0) {
 				printf("Huh b, port is %d not net:%p %d?\n",
 				       ((const struct sockaddr_in *)to)->sin_port,
@@ -1957,24 +1944,17 @@ sctp_process_a_data_chunk(struct sctp_tc
 			dmbuf = tmp;
 		}
 		to = rtcache_getdst(&net->ro);
 		if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 		    to->sa_family == AF_INET) {
 			const struct sockaddr_in *sin;
 
 			sin = satocsin(to);
-			memset(&sin6, 0, sizeof(sin6));
-			sin6.sin6_family = AF_INET6;
-			sin6.sin6_len = sizeof(struct sockaddr_in6);
-			sin6.sin6_addr.s6_addr16[2] = 0xffff;
-			bcopy(&sin->sin_addr,
-			    &sin6.sin6_addr.s6_addr16[3],
-			    sizeof(sin6.sin6_addr.s6_addr16[3]));
-			sin6.sin6_port = sin->sin_port;
+			in6_sin_2_v4mapsin6(sin, &sin6);
 			to = (struct sockaddr *)&sin6;
 		}
 
 		/* check and strip embedded scope junk */
 		to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 		    &lsa6);
 		if (((const struct sockaddr_in *)to)->sin_port == 0) {
 			printf("Huh c, port is %d not net:%p %d?\n",
Index: netinet/sctputil.c
===================================================================
RCS file: /cvsroot/src/sys/netinet/sctputil.c,v
retrieving revision 1.1
diff -p -u -U 8 -r1.1 sctputil.c
--- netinet/sctputil.c	13 Oct 2015 21:28:35 -0000	1.1
+++ netinet/sctputil.c	15 Feb 2016 15:10:21 -0000
@@ -2082,23 +2082,17 @@ sctp_notify_assoc_change(u_int32_t event
 
 	/* append to socket */
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    to->sa_family == AF_INET) {
 		const struct sockaddr_in *sin;
 
 		sin = (const struct sockaddr_in *)to;
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		memcpy(&sin6.sin6_addr.s6_addr16[3], &sin->sin_addr,
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 						   &lsa6);
 	/*
 	 * We need to always notify comm changes.
 	 * if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
@@ -2174,23 +2168,17 @@ sctp_notify_peer_addr_change(struct sctp
 	m_notify->m_next = NULL;
 
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    to->sa_family == AF_INET) {
 		const struct sockaddr_in *sin;
 
 		sin = (const struct sockaddr_in *)to;
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 	    &lsa6);
 
 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
 		sctp_m_freem(m_notify);
@@ -2274,23 +2262,17 @@ sctp_notify_send_failed(struct sctp_tcb 
 	/* Steal off the mbuf */
 	chk->data = NULL;
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    to->sa_family == AF_INET) {
 		const struct sockaddr_in *sin;
 
 		sin = satocsin(to);
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 						   &lsa6);
 
 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
 		sctp_m_freem(m_notify);
@@ -2352,23 +2334,17 @@ sctp_notify_adaption_layer(struct sctp_t
 	m_notify->m_next = NULL;
 
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    (to->sa_family == AF_INET)) {
 		const struct sockaddr_in *sin;
 
 		sin = satocsin(to);
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 						   &lsa6);
 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
 		sctp_m_freem(m_notify);
 		return;
@@ -2428,23 +2404,17 @@ sctp_notify_partial_delivery_indication(
 	m_notify->m_next = NULL;
 
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    (to->sa_family == AF_INET)) {
 		const struct sockaddr_in *sin;
 
 		sin = satocsin(to);
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 						   &lsa6);
 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
 		sctp_m_freem(m_notify);
 		return;
@@ -2513,23 +2483,17 @@ sctp_notify_shutdown_event(struct sctp_t
 	m_notify->m_next = NULL;
 
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    to->sa_family == AF_INET) {
 		const struct sockaddr_in *sin;
 
 		sin = satocsin(to);
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *)sctp_recover_scope((const struct sockaddr_in6 *)to,
 	    &lsa6);
 	if (sctp_sbspace(&stcb->sctp_socket->so_rcv) < m_notify->m_len) {
 		sctp_m_freem(m_notify);
 		return;
@@ -2615,23 +2579,17 @@ sctp_notify_stream_reset(struct sctp_tcb
 		return;
 	}
 	to = rtcache_getdst(&stcb->asoc.primary_destination->ro);
 	if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
 	    to->sa_family == AF_INET) {
 		const struct sockaddr_in *sin;
 
 		sin = satocsin(to);
-		memset(&sin6, 0, sizeof(sin6));
-		sin6.sin6_family = AF_INET6;
-		sin6.sin6_len = sizeof(struct sockaddr_in6);
-		sin6.sin6_addr.s6_addr16[2] = 0xffff;
-		bcopy(&sin->sin_addr, &sin6.sin6_addr.s6_addr16[3],
-		    sizeof(sin6.sin6_addr.s6_addr16[3]));
-		sin6.sin6_port = sin->sin_port;
+		in6_sin_2_v4mapsin6(sin, &sin6);
 		to = (struct sockaddr *)&sin6;
 	}
 	/* check and strip embedded scope junk */
 	to = (const struct sockaddr *) sctp_recover_scope((const struct sockaddr_in6 *)to,
 	    &lsa6);
 	/* append to socket */
 	SCTP_TCB_UNLOCK(stcb);
 	SCTP_INP_WLOCK(stcb->sctp_ep);


Home | Main Index | Thread Index | Old Index