aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp/ipv6.c
diff options
context:
space:
mode:
authorJames Morris <james.l.morris@oracle.com>2014-11-19 05:32:12 -0500
committerJames Morris <james.l.morris@oracle.com>2014-11-19 05:32:12 -0500
commitb10778a00d40b3d9fdaaf5891e802794781ff71c (patch)
tree6ba4cbac86eecedc3f30650e7f764ecf00c83898 /net/sctp/ipv6.c
parent594081ee7145cc30a3977cb4e218f81213b63dc5 (diff)
parentbfe01a5ba2490f299e1d2d5508cbbbadd897bbe9 (diff)
Merge commit 'v3.17' into next
Diffstat (limited to 'net/sctp/ipv6.c')
-rw-r--r--net/sctp/ipv6.c156
1 files changed, 82 insertions, 74 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