diff options
-rw-r--r-- | include/net/sctp/sctp.h | 2 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 8 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 156 | ||||
-rw-r--r-- | net/sctp/protocol.c | 12 | ||||
-rw-r--r-- | net/sctp/socket.c | 33 | ||||
-rw-r--r-- | net/sctp/transport.c | 4 | ||||
-rw-r--r-- | net/sctp/ulpevent.c | 2 |
7 files changed, 112 insertions, 105 deletions
diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h index 90c1cccd164d..f6e7397e799d 100644 --- a/include/net/sctp/sctp.h +++ b/include/net/sctp/sctp.h | |||
@@ -554,6 +554,8 @@ static inline void sctp_v6_map_v4(union sctp_addr *addr) | |||
554 | static inline void sctp_v4_map_v6(union sctp_addr *addr) | 554 | static inline void sctp_v4_map_v6(union sctp_addr *addr) |
555 | { | 555 | { |
556 | addr->v6.sin6_family = AF_INET6; | 556 | addr->v6.sin6_family = AF_INET6; |
557 | addr->v6.sin6_flowinfo = 0; | ||
558 | addr->v6.sin6_scope_id = 0; | ||
557 | addr->v6.sin6_port = addr->v4.sin_port; | 559 | addr->v6.sin6_port = addr->v4.sin_port; |
558 | addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr; | 560 | addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr; |
559 | addr->v6.sin6_addr.s6_addr32[0] = 0; | 561 | addr->v6.sin6_addr.s6_addr32[0] = 0; |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 7741d1b66967..4ff3f67be62c 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -465,10 +465,6 @@ struct sctp_af { | |||
465 | int saddr); | 465 | int saddr); |
466 | void (*from_sk) (union sctp_addr *, | 466 | void (*from_sk) (union sctp_addr *, |
467 | struct sock *sk); | 467 | struct sock *sk); |
468 | void (*to_sk_saddr) (union sctp_addr *, | ||
469 | struct sock *sk); | ||
470 | void (*to_sk_daddr) (union sctp_addr *, | ||
471 | struct sock *sk); | ||
472 | void (*from_addr_param) (union sctp_addr *, | 468 | void (*from_addr_param) (union sctp_addr *, |
473 | union sctp_addr_param *, | 469 | union sctp_addr_param *, |
474 | __be16 port, int iif); | 470 | __be16 port, int iif); |
@@ -509,7 +505,9 @@ struct sctp_pf { | |||
509 | int (*supported_addrs)(const struct sctp_sock *, __be16 *); | 505 | int (*supported_addrs)(const struct sctp_sock *, __be16 *); |
510 | struct sock *(*create_accept_sk) (struct sock *sk, | 506 | struct sock *(*create_accept_sk) (struct sock *sk, |
511 | struct sctp_association *asoc); | 507 | struct sctp_association *asoc); |
512 | void (*addr_v4map) (struct sctp_sock *, union sctp_addr *); | 508 | int (*addr_to_user)(struct sctp_sock *sk, union sctp_addr *addr); |
509 | void (*to_sk_saddr)(union sctp_addr *, struct sock *sk); | ||
510 | void (*to_sk_daddr)(union sctp_addr *, struct sock *sk); | ||
513 | struct sctp_af *af; | 511 | struct sctp_af *af; |
514 | }; | 512 | }; |
515 | 513 | ||
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. */ |
435 | static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | 435 | static 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. */ |
449 | static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) | 449 | static 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 |
679 | static 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 | */ | ||
677 | static 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. */ | ||
710 | static 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. */ |
722 | static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, | 718 | static 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. */ |
758 | static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, | 751 | static 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() */ | ||
909 | static 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 | |||
917 | static const struct proto_ops inet6_seqpacket_ops = { | 925 | static 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 */ | 579 | static int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) |
580 | static 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 | |||
4413 | int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) | 4413 | int 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 | ||