aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJason Gunthorpe <jgunthorpe@obsidianresearch.com>2014-07-30 14:40:53 -0400
committerDavid S. Miller <davem@davemloft.net>2014-08-01 00:49:06 -0400
commit299ee123e19889d511092347f5fc14db0f10e3a6 (patch)
treef3ce40430141d39fbcc5aeaf54d3a6018fdd6842 /net
parent536721b1cb3fb50034bf6f6c7a7ea16166970e69 (diff)
sctp: Fixup v4mapped behaviour to comply with Sock API
The SCTP socket extensions API document describes the v4mapping option as follows: 8.1.15. Set/Clear IPv4 Mapped Addresses (SCTP_I_WANT_MAPPED_V4_ADDR) This socket option is a Boolean flag which turns on or off the mapping of IPv4 addresses. If this option is turned on, then IPv4 addresses will be mapped to V6 representation. If this option is turned off, then no mapping will be done of V4 addresses and a user will receive both PF_INET6 and PF_INET type addresses on the socket. See [RFC3542] for more details on mapped V6 addresses. This description isn't really in line with what the code does though. Introduce addr_to_user (renamed addr_v4map), which should be called before any sockaddr is passed back to user space. The new function places the sockaddr into the correct format depending on the SCTP_I_WANT_MAPPED_V4_ADDR option. Audit all places that touched v4mapped and either sanely construct a v4 or v6 address then call addr_to_user, or drop the unnecessary v4mapped check entirely. Audit all places that call addr_to_user and verify they are on a sycall return path. Add a custom getname that formats the address properly. Several bugs are addressed: - SCTP_I_WANT_MAPPED_V4_ADDR=0 often returned garbage for addresses to user space - The addr_len returned from recvmsg was not correct when returning AF_INET on a v6 socket - flowlabel and scope_id were not zerod when promoting a v4 to v6 - Some syscalls like bind and connect behaved differently depending on v4mapped Tested bind, getpeername, getsockname, connect, and recvmsg for proper behaviour in v4mapped = 1 and 0 cases. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Tested-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/ipv6.c156
-rw-r--r--net/sctp/protocol.c12
-rw-r--r--net/sctp/socket.c33
-rw-r--r--net/sctp/transport.c4
-rw-r--r--net/sctp/ulpevent.c2
5 files changed, 107 insertions, 100 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 1999592ba88c..0e4198ee2370 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -434,7 +434,7 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
434/* Initialize sk->sk_rcv_saddr from sctp_addr. */ 434/* Initialize sk->sk_rcv_saddr from sctp_addr. */
435static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) 435static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
436{ 436{
437 if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { 437 if (addr->sa.sa_family == AF_INET) {
438 sk->sk_v6_rcv_saddr.s6_addr32[0] = 0; 438 sk->sk_v6_rcv_saddr.s6_addr32[0] = 0;
439 sk->sk_v6_rcv_saddr.s6_addr32[1] = 0; 439 sk->sk_v6_rcv_saddr.s6_addr32[1] = 0;
440 sk->sk_v6_rcv_saddr.s6_addr32[2] = htonl(0x0000ffff); 440 sk->sk_v6_rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
@@ -448,7 +448,7 @@ static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
448/* Initialize sk->sk_daddr from sctp_addr. */ 448/* Initialize sk->sk_daddr from sctp_addr. */
449static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) 449static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
450{ 450{
451 if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { 451 if (addr->sa.sa_family == AF_INET) {
452 sk->sk_v6_daddr.s6_addr32[0] = 0; 452 sk->sk_v6_daddr.s6_addr32[0] = 0;
453 sk->sk_v6_daddr.s6_addr32[1] = 0; 453 sk->sk_v6_daddr.s6_addr32[1] = 0;
454 sk->sk_v6_daddr.s6_addr32[2] = htonl(0x0000ffff); 454 sk->sk_v6_daddr.s6_addr32[2] = htonl(0x0000ffff);
@@ -556,8 +556,6 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
556 if (IPV6_ADDR_ANY == type) 556 if (IPV6_ADDR_ANY == type)
557 return 1; 557 return 1;
558 if (type == IPV6_ADDR_MAPPED) { 558 if (type == IPV6_ADDR_MAPPED) {
559 if (sp && !sp->v4mapped)
560 return 0;
561 if (sp && ipv6_only_sock(sctp_opt2sk(sp))) 559 if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
562 return 0; 560 return 0;
563 sctp_v6_map_v4(addr); 561 sctp_v6_map_v4(addr);
@@ -587,8 +585,6 @@ static int sctp_v6_addr_valid(union sctp_addr *addr,
587 /* Note: This routine is used in input, so v4-mapped-v6 585 /* Note: This routine is used in input, so v4-mapped-v6
588 * are disallowed here when there is no sctp_sock. 586 * are disallowed here when there is no sctp_sock.
589 */ 587 */
590 if (!sp || !sp->v4mapped)
591 return 0;
592 if (sp && ipv6_only_sock(sctp_opt2sk(sp))) 588 if (sp && ipv6_only_sock(sctp_opt2sk(sp)))
593 return 0; 589 return 0;
594 sctp_v6_map_v4(addr); 590 sctp_v6_map_v4(addr);
@@ -675,11 +671,23 @@ out:
675 return newsk; 671 return newsk;
676} 672}
677 673
678/* Map v4 address to mapped v6 address */ 674/* Format a sockaddr for return to user space. This makes sure the return is
679static void sctp_v6_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr) 675 * AF_INET or AF_INET6 depending on the SCTP_I_WANT_MAPPED_V4_ADDR option.
676 */
677static int sctp_v6_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr)
680{ 678{
681 if (sp->v4mapped && AF_INET == addr->sa.sa_family) 679 if (sp->v4mapped) {
682 sctp_v4_map_v6(addr); 680 if (addr->sa.sa_family == AF_INET)
681 sctp_v4_map_v6(addr);
682 } else {
683 if (addr->sa.sa_family == AF_INET6 &&
684 ipv6_addr_v4mapped(&addr->v6.sin6_addr))
685 sctp_v6_map_v4(addr);
686 }
687
688 if (addr->sa.sa_family == AF_INET)
689 return sizeof(struct sockaddr_in);
690 return sizeof(struct sockaddr_in6);
683} 691}
684 692
685/* Where did this skb come from? */ 693/* Where did this skb come from? */
@@ -706,82 +714,68 @@ static void sctp_v6_ecn_capable(struct sock *sk)
706 inet6_sk(sk)->tclass |= INET_ECN_ECT_0; 714 inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
707} 715}
708 716
709/* Initialize a PF_INET6 socket msg_name. */
710static void sctp_inet6_msgname(char *msgname, int *addr_len)
711{
712 struct sockaddr_in6 *sin6;
713
714 sin6 = (struct sockaddr_in6 *)msgname;
715 sin6->sin6_family = AF_INET6;
716 sin6->sin6_flowinfo = 0;
717 sin6->sin6_scope_id = 0; /*FIXME */
718 *addr_len = sizeof(struct sockaddr_in6);
719}
720
721/* Initialize a PF_INET msgname from a ulpevent. */ 717/* Initialize a PF_INET msgname from a ulpevent. */
722static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, 718static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
723 char *msgname, int *addrlen) 719 char *msgname, int *addrlen)
724{ 720{
725 struct sockaddr_in6 *sin6, *sin6from; 721 union sctp_addr *addr;
726 722 struct sctp_association *asoc;
727 if (msgname) { 723 union sctp_addr *paddr;
728 union sctp_addr *addr;
729 struct sctp_association *asoc;
730
731 asoc = event->asoc;
732 sctp_inet6_msgname(msgname, addrlen);
733 sin6 = (struct sockaddr_in6 *)msgname;
734 sin6->sin6_port = htons(asoc->peer.port);
735 addr = &asoc->peer.primary_addr;
736 724
737 /* Note: If we go to a common v6 format, this code 725 if (!msgname)
738 * will change. 726 return;
739 */
740 727
741 /* Map ipv4 address into v4-mapped-on-v6 address. */ 728 addr = (union sctp_addr *)msgname;
742 if (sctp_sk(asoc->base.sk)->v4mapped && 729 asoc = event->asoc;
743 AF_INET == addr->sa.sa_family) { 730 paddr = &asoc->peer.primary_addr;
744 sctp_v4_map_v6((union sctp_addr *)sin6);
745 sin6->sin6_addr.s6_addr32[3] =
746 addr->v4.sin_addr.s_addr;
747 return;
748 }
749 731
750 sin6from = &asoc->peer.primary_addr.v6; 732 if (paddr->sa.sa_family == AF_INET) {
751 sin6->sin6_addr = sin6from->sin6_addr; 733 addr->v4.sin_family = AF_INET;
752 if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) 734 addr->v4.sin_port = htons(asoc->peer.port);
753 sin6->sin6_scope_id = sin6from->sin6_scope_id; 735 addr->v4.sin_addr = paddr->v4.sin_addr;
736 } else {
737 addr->v6.sin6_family = AF_INET6;
738 addr->v6.sin6_flowinfo = 0;
739 if (ipv6_addr_type(&paddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
740 addr->v6.sin6_scope_id = paddr->v6.sin6_scope_id;
741 else
742 addr->v6.sin6_scope_id = 0;
743 addr->v6.sin6_port = htons(asoc->peer.port);
744 addr->v6.sin6_addr = paddr->v6.sin6_addr;
754 } 745 }
746
747 *addrlen = sctp_v6_addr_to_user(sctp_sk(asoc->base.sk), addr);
755} 748}
756 749
757/* Initialize a msg_name from an inbound skb. */ 750/* Initialize a msg_name from an inbound skb. */
758static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, 751static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
759 int *addr_len) 752 int *addr_len)
760{ 753{
754 union sctp_addr *addr;
761 struct sctphdr *sh; 755 struct sctphdr *sh;
762 struct sockaddr_in6 *sin6;
763
764 if (msgname) {
765 sctp_inet6_msgname(msgname, addr_len);
766 sin6 = (struct sockaddr_in6 *)msgname;
767 sh = sctp_hdr(skb);
768 sin6->sin6_port = sh->source;
769
770 /* Map ipv4 address into v4-mapped-on-v6 address. */
771 if (sctp_sk(skb->sk)->v4mapped &&
772 ip_hdr(skb)->version == 4) {
773 sctp_v4_map_v6((union sctp_addr *)sin6);
774 sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr;
775 return;
776 }
777 756
778 /* Otherwise, just copy the v6 address. */ 757 if (!msgname)
779 sin6->sin6_addr = ipv6_hdr(skb)->saddr; 758 return;
780 if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { 759
760 addr = (union sctp_addr *)msgname;
761 sh = sctp_hdr(skb);
762
763 if (ip_hdr(skb)->version == 4) {
764 addr->v4.sin_family = AF_INET;
765 addr->v4.sin_port = sh->source;
766 addr->v4.sin_addr.s_addr = ip_hdr(skb)->saddr;
767 } else {
768 addr->v6.sin6_family = AF_INET6;
769 addr->v6.sin6_flowinfo = 0;
770 addr->v6.sin6_port = sh->source;
771 addr->v6.sin6_addr = ipv6_hdr(skb)->saddr;
772 if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
781 struct sctp_ulpevent *ev = sctp_skb2event(skb); 773 struct sctp_ulpevent *ev = sctp_skb2event(skb);
782 sin6->sin6_scope_id = ev->iif; 774 addr->v6.sin6_scope_id = ev->iif;
783 } 775 }
784 } 776 }
777
778 *addr_len = sctp_v6_addr_to_user(sctp_sk(skb->sk), addr);
785} 779}
786 780
787/* Do we support this AF? */ 781/* Do we support this AF? */
@@ -857,9 +851,6 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
857 return 0; 851 return 0;
858 } 852 }
859 rcu_read_unlock(); 853 rcu_read_unlock();
860 } else if (type == IPV6_ADDR_MAPPED) {
861 if (!opt->v4mapped)
862 return 0;
863 } 854 }
864 855
865 af = opt->pf->af; 856 af = opt->pf->af;
@@ -914,6 +905,23 @@ static int sctp_inet6_supported_addrs(const struct sctp_sock *opt,
914 return 1; 905 return 1;
915} 906}
916 907
908/* Handle SCTP_I_WANT_MAPPED_V4_ADDR for getpeername() and getsockname() */
909static int sctp_getname(struct socket *sock, struct sockaddr *uaddr,
910 int *uaddr_len, int peer)
911{
912 int rc;
913
914 rc = inet6_getname(sock, uaddr, uaddr_len, peer);
915
916 if (rc != 0)
917 return rc;
918
919 *uaddr_len = sctp_v6_addr_to_user(sctp_sk(sock->sk),
920 (union sctp_addr *)uaddr);
921
922 return rc;
923}
924
917static const struct proto_ops inet6_seqpacket_ops = { 925static const struct proto_ops inet6_seqpacket_ops = {
918 .family = PF_INET6, 926 .family = PF_INET6,
919 .owner = THIS_MODULE, 927 .owner = THIS_MODULE,
@@ -922,7 +930,7 @@ static const struct proto_ops inet6_seqpacket_ops = {
922 .connect = inet_dgram_connect, 930 .connect = inet_dgram_connect,
923 .socketpair = sock_no_socketpair, 931 .socketpair = sock_no_socketpair,
924 .accept = inet_accept, 932 .accept = inet_accept,
925 .getname = inet6_getname, 933 .getname = sctp_getname,
926 .poll = sctp_poll, 934 .poll = sctp_poll,
927 .ioctl = inet6_ioctl, 935 .ioctl = inet6_ioctl,
928 .listen = sctp_inet_listen, 936 .listen = sctp_inet_listen,
@@ -974,8 +982,6 @@ static struct sctp_af sctp_af_inet6 = {
974 .copy_addrlist = sctp_v6_copy_addrlist, 982 .copy_addrlist = sctp_v6_copy_addrlist,
975 .from_skb = sctp_v6_from_skb, 983 .from_skb = sctp_v6_from_skb,
976 .from_sk = sctp_v6_from_sk, 984 .from_sk = sctp_v6_from_sk,
977 .to_sk_saddr = sctp_v6_to_sk_saddr,
978 .to_sk_daddr = sctp_v6_to_sk_daddr,
979 .from_addr_param = sctp_v6_from_addr_param, 985 .from_addr_param = sctp_v6_from_addr_param,
980 .to_addr_param = sctp_v6_to_addr_param, 986 .to_addr_param = sctp_v6_to_addr_param,
981 .cmp_addr = sctp_v6_cmp_addr, 987 .cmp_addr = sctp_v6_cmp_addr,
@@ -1005,7 +1011,9 @@ static struct sctp_pf sctp_pf_inet6 = {
1005 .send_verify = sctp_inet6_send_verify, 1011 .send_verify = sctp_inet6_send_verify,
1006 .supported_addrs = sctp_inet6_supported_addrs, 1012 .supported_addrs = sctp_inet6_supported_addrs,
1007 .create_accept_sk = sctp_v6_create_accept_sk, 1013 .create_accept_sk = sctp_v6_create_accept_sk,
1008 .addr_v4map = sctp_v6_addr_v4map, 1014 .addr_to_user = sctp_v6_addr_to_user,
1015 .to_sk_saddr = sctp_v6_to_sk_saddr,
1016 .to_sk_daddr = sctp_v6_to_sk_daddr,
1009 .af = &sctp_af_inet6, 1017 .af = &sctp_af_inet6,
1010}; 1018};
1011 1019
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 6789d785e698..6240834f4b95 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -576,10 +576,10 @@ out:
576 return newsk; 576 return newsk;
577} 577}
578 578
579/* Map address, empty for v4 family */ 579static int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr)
580static void sctp_v4_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr)
581{ 580{
582 /* Empty */ 581 /* No address mapping for V4 sockets */
582 return sizeof(struct sockaddr_in);
583} 583}
584 584
585/* Dump the v4 addr to the seq file. */ 585/* Dump the v4 addr to the seq file. */
@@ -976,7 +976,9 @@ static struct sctp_pf sctp_pf_inet = {
976 .send_verify = sctp_inet_send_verify, 976 .send_verify = sctp_inet_send_verify,
977 .supported_addrs = sctp_inet_supported_addrs, 977 .supported_addrs = sctp_inet_supported_addrs,
978 .create_accept_sk = sctp_v4_create_accept_sk, 978 .create_accept_sk = sctp_v4_create_accept_sk,
979 .addr_v4map = sctp_v4_addr_v4map, 979 .addr_to_user = sctp_v4_addr_to_user,
980 .to_sk_saddr = sctp_v4_to_sk_saddr,
981 .to_sk_daddr = sctp_v4_to_sk_daddr,
980 .af = &sctp_af_inet 982 .af = &sctp_af_inet
981}; 983};
982 984
@@ -1047,8 +1049,6 @@ static struct sctp_af sctp_af_inet = {
1047 .copy_addrlist = sctp_v4_copy_addrlist, 1049 .copy_addrlist = sctp_v4_copy_addrlist,
1048 .from_skb = sctp_v4_from_skb, 1050 .from_skb = sctp_v4_from_skb,
1049 .from_sk = sctp_v4_from_sk, 1051 .from_sk = sctp_v4_from_sk,
1050 .to_sk_saddr = sctp_v4_to_sk_saddr,
1051 .to_sk_daddr = sctp_v4_to_sk_daddr,
1052 .from_addr_param = sctp_v4_from_addr_param, 1052 .from_addr_param = sctp_v4_from_addr_param,
1053 .to_addr_param = sctp_v4_to_addr_param, 1053 .to_addr_param = sctp_v4_to_addr_param,
1054 .cmp_addr = sctp_v4_cmp_addr, 1054 .cmp_addr = sctp_v4_cmp_addr,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 743308f40544..eb71d49e7653 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -254,7 +254,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
254 if (id_asoc && (id_asoc != addr_asoc)) 254 if (id_asoc && (id_asoc != addr_asoc))
255 return NULL; 255 return NULL;
256 256
257 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), 257 sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk),
258 (union sctp_addr *)addr); 258 (union sctp_addr *)addr);
259 259
260 return transport; 260 return transport;
@@ -396,7 +396,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
396 /* Copy back into socket for getsockname() use. */ 396 /* Copy back into socket for getsockname() use. */
397 if (!ret) { 397 if (!ret) {
398 inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); 398 inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num);
399 af->to_sk_saddr(addr, sk); 399 sp->pf->to_sk_saddr(addr, sk);
400 } 400 }
401 401
402 return ret; 402 return ret;
@@ -1053,7 +1053,6 @@ static int __sctp_connect(struct sock *sk,
1053 struct sctp_association *asoc2; 1053 struct sctp_association *asoc2;
1054 struct sctp_transport *transport; 1054 struct sctp_transport *transport;
1055 union sctp_addr to; 1055 union sctp_addr to;
1056 struct sctp_af *af;
1057 sctp_scope_t scope; 1056 sctp_scope_t scope;
1058 long timeo; 1057 long timeo;
1059 int err = 0; 1058 int err = 0;
@@ -1081,6 +1080,8 @@ static int __sctp_connect(struct sock *sk,
1081 /* Walk through the addrs buffer and count the number of addresses. */ 1080 /* Walk through the addrs buffer and count the number of addresses. */
1082 addr_buf = kaddrs; 1081 addr_buf = kaddrs;
1083 while (walk_size < addrs_size) { 1082 while (walk_size < addrs_size) {
1083 struct sctp_af *af;
1084
1084 if (walk_size + sizeof(sa_family_t) > addrs_size) { 1085 if (walk_size + sizeof(sa_family_t) > addrs_size) {
1085 err = -EINVAL; 1086 err = -EINVAL;
1086 goto out_free; 1087 goto out_free;
@@ -1205,8 +1206,7 @@ static int __sctp_connect(struct sock *sk,
1205 1206
1206 /* Initialize sk's dport and daddr for getpeername() */ 1207 /* Initialize sk's dport and daddr for getpeername() */
1207 inet_sk(sk)->inet_dport = htons(asoc->peer.port); 1208 inet_sk(sk)->inet_dport = htons(asoc->peer.port);
1208 af = sctp_get_af_specific(sa_addr->sa.sa_family); 1209 sp->pf->to_sk_daddr(sa_addr, sk);
1209 af->to_sk_daddr(sa_addr, sk);
1210 sk->sk_err = 0; 1210 sk->sk_err = 0;
1211 1211
1212 /* in-kernel sockets don't generally have a file allocated to them 1212 /* in-kernel sockets don't generally have a file allocated to them
@@ -4255,7 +4255,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
4255 memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr, 4255 memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr,
4256 transport->af_specific->sockaddr_len); 4256 transport->af_specific->sockaddr_len);
4257 /* Map ipv4 address into v4-mapped-on-v6 address. */ 4257 /* Map ipv4 address into v4-mapped-on-v6 address. */
4258 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), 4258 sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk),
4259 (union sctp_addr *)&status.sstat_primary.spinfo_address); 4259 (union sctp_addr *)&status.sstat_primary.spinfo_address);
4260 status.sstat_primary.spinfo_state = transport->state; 4260 status.sstat_primary.spinfo_state = transport->state;
4261 status.sstat_primary.spinfo_cwnd = transport->cwnd; 4261 status.sstat_primary.spinfo_cwnd = transport->cwnd;
@@ -4413,8 +4413,8 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv
4413int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) 4413int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
4414{ 4414{
4415 struct sctp_association *asoc = sctp_id2assoc(sk, id); 4415 struct sctp_association *asoc = sctp_id2assoc(sk, id);
4416 struct sctp_sock *sp = sctp_sk(sk);
4416 struct socket *sock; 4417 struct socket *sock;
4417 struct sctp_af *af;
4418 int err = 0; 4418 int err = 0;
4419 4419
4420 if (!asoc) 4420 if (!asoc)
@@ -4436,8 +4436,7 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp)
4436 /* Make peeled-off sockets more like 1-1 accepted sockets. 4436 /* Make peeled-off sockets more like 1-1 accepted sockets.
4437 * Set the daddr and initialize id to something more random 4437 * Set the daddr and initialize id to something more random
4438 */ 4438 */
4439 af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); 4439 sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk);
4440 af->to_sk_daddr(&asoc->peer.primary_addr, sk);
4441 4440
4442 /* Populate the fields of the newsk from the oldsk and migrate the 4441 /* Populate the fields of the newsk from the oldsk and migrate the
4443 * asoc to the newsk. 4442 * asoc to the newsk.
@@ -4821,8 +4820,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
4821 list_for_each_entry(from, &asoc->peer.transport_addr_list, 4820 list_for_each_entry(from, &asoc->peer.transport_addr_list,
4822 transports) { 4821 transports) {
4823 memcpy(&temp, &from->ipaddr, sizeof(temp)); 4822 memcpy(&temp, &from->ipaddr, sizeof(temp));
4824 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 4823 addrlen = sctp_get_pf_specific(sk->sk_family)
4825 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4824 ->addr_to_user(sp, &temp);
4826 if (space_left < addrlen) 4825 if (space_left < addrlen)
4827 return -ENOMEM; 4826 return -ENOMEM;
4828 if (copy_to_user(to, &temp, addrlen)) 4827 if (copy_to_user(to, &temp, addrlen))
@@ -4866,9 +4865,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
4866 if (!temp.v4.sin_port) 4865 if (!temp.v4.sin_port)
4867 temp.v4.sin_port = htons(port); 4866 temp.v4.sin_port = htons(port);
4868 4867
4869 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), 4868 addrlen = sctp_get_pf_specific(sk->sk_family)
4870 &temp); 4869 ->addr_to_user(sctp_sk(sk), &temp);
4871 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4870
4872 if (space_left < addrlen) { 4871 if (space_left < addrlen) {
4873 cnt = -ENOMEM; 4872 cnt = -ENOMEM;
4874 break; 4873 break;
@@ -4956,8 +4955,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
4956 */ 4955 */
4957 list_for_each_entry(addr, &bp->address_list, list) { 4956 list_for_each_entry(addr, &bp->address_list, list) {
4958 memcpy(&temp, &addr->a, sizeof(temp)); 4957 memcpy(&temp, &addr->a, sizeof(temp));
4959 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); 4958 addrlen = sctp_get_pf_specific(sk->sk_family)
4960 addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; 4959 ->addr_to_user(sp, &temp);
4961 if (space_left < addrlen) { 4960 if (space_left < addrlen) {
4962 err = -ENOMEM; /*fixme: right error?*/ 4961 err = -ENOMEM; /*fixme: right error?*/
4963 goto out; 4962 goto out;
@@ -5016,7 +5015,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
5016 memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, 5015 memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr,
5017 asoc->peer.primary_path->af_specific->sockaddr_len); 5016 asoc->peer.primary_path->af_specific->sockaddr_len);
5018 5017
5019 sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, 5018 sctp_get_pf_specific(sk->sk_family)->addr_to_user(sp,
5020 (union sctp_addr *)&prim.ssp_addr); 5019 (union sctp_addr *)&prim.ssp_addr);
5021 5020
5022 if (put_user(len, optlen)) 5021 if (put_user(len, optlen))
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index b10e047bbd15..a0a431824f63 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -289,8 +289,8 @@ void sctp_transport_route(struct sctp_transport *transport,
289 */ 289 */
290 if (asoc && (!asoc->peer.primary_path || 290 if (asoc && (!asoc->peer.primary_path ||
291 (transport == asoc->peer.active_path))) 291 (transport == asoc->peer.active_path)))
292 opt->pf->af->to_sk_saddr(&transport->saddr, 292 opt->pf->to_sk_saddr(&transport->saddr,
293 asoc->base.sk); 293 asoc->base.sk);
294 } else 294 } else
295 transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; 295 transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
296} 296}
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index e049298ecfa0..d1e38308f615 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -341,7 +341,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
341 memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); 341 memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage));
342 342
343 /* Map ipv4 address into v4-mapped-on-v6 address. */ 343 /* Map ipv4 address into v4-mapped-on-v6 address. */
344 sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map( 344 sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_to_user(
345 sctp_sk(asoc->base.sk), 345 sctp_sk(asoc->base.sk),
346 (union sctp_addr *)&spc->spc_aaddr); 346 (union sctp_addr *)&spc->spc_aaddr);
347 347