aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVlad Yasevich <vladislav.yasevich@hp.com>2007-08-01 10:56:43 -0400
committerVlad Yasevich <vladislav.yasevich@hp.com>2007-08-01 11:19:06 -0400
commite4d1feab5df035312494ce3037ac5f041d0f5fc9 (patch)
tree9ed83f1037b0df8478c29143357ea4e66314d364 /net
parentb225b884a18a1932db5414abd3ef94a45e4e348e (diff)
SCTP: IPv4 mapped addr not returned in SCTPv6 accept()
When issuing a connect call on an AF_INET6 sctp socket with a IPv4-mapped destination, the peer address that is returned by getpeeraddr() should be v4-mapped as well. Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>
Diffstat (limited to 'net')
-rw-r--r--net/sctp/socket.c20
1 files changed, 11 insertions, 9 deletions
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index be743d4a7c09..01c6364245b7 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -975,7 +975,7 @@ static int __sctp_connect(struct sock* sk,
975 int err = 0; 975 int err = 0;
976 int addrcnt = 0; 976 int addrcnt = 0;
977 int walk_size = 0; 977 int walk_size = 0;
978 union sctp_addr *sa_addr; 978 union sctp_addr *sa_addr = NULL;
979 void *addr_buf; 979 void *addr_buf;
980 unsigned short port; 980 unsigned short port;
981 unsigned int f_flags = 0; 981 unsigned int f_flags = 0;
@@ -1009,7 +1009,10 @@ static int __sctp_connect(struct sock* sk,
1009 goto out_free; 1009 goto out_free;
1010 } 1010 }
1011 1011
1012 err = sctp_verify_addr(sk, sa_addr, af->sockaddr_len); 1012 /* Save current address so we can work with it */
1013 memcpy(&to, sa_addr, af->sockaddr_len);
1014
1015 err = sctp_verify_addr(sk, &to, af->sockaddr_len);
1013 if (err) 1016 if (err)
1014 goto out_free; 1017 goto out_free;
1015 1018
@@ -1019,12 +1022,11 @@ static int __sctp_connect(struct sock* sk,
1019 if (asoc && asoc->peer.port && asoc->peer.port != port) 1022 if (asoc && asoc->peer.port && asoc->peer.port != port)
1020 goto out_free; 1023 goto out_free;
1021 1024
1022 memcpy(&to, sa_addr, af->sockaddr_len);
1023 1025
1024 /* Check if there already is a matching association on the 1026 /* Check if there already is a matching association on the
1025 * endpoint (other than the one created here). 1027 * endpoint (other than the one created here).
1026 */ 1028 */
1027 asoc2 = sctp_endpoint_lookup_assoc(ep, sa_addr, &transport); 1029 asoc2 = sctp_endpoint_lookup_assoc(ep, &to, &transport);
1028 if (asoc2 && asoc2 != asoc) { 1030 if (asoc2 && asoc2 != asoc) {
1029 if (asoc2->state >= SCTP_STATE_ESTABLISHED) 1031 if (asoc2->state >= SCTP_STATE_ESTABLISHED)
1030 err = -EISCONN; 1032 err = -EISCONN;
@@ -1037,7 +1039,7 @@ static int __sctp_connect(struct sock* sk,
1037 * make sure that there is no peeled-off association matching 1039 * make sure that there is no peeled-off association matching
1038 * the peer address even on another socket. 1040 * the peer address even on another socket.
1039 */ 1041 */
1040 if (sctp_endpoint_is_peeled_off(ep, sa_addr)) { 1042 if (sctp_endpoint_is_peeled_off(ep, &to)) {
1041 err = -EADDRNOTAVAIL; 1043 err = -EADDRNOTAVAIL;
1042 goto out_free; 1044 goto out_free;
1043 } 1045 }
@@ -1068,7 +1070,7 @@ static int __sctp_connect(struct sock* sk,
1068 } 1070 }
1069 } 1071 }
1070 1072
1071 scope = sctp_scope(sa_addr); 1073 scope = sctp_scope(&to);
1072 asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL); 1074 asoc = sctp_association_new(ep, sk, scope, GFP_KERNEL);
1073 if (!asoc) { 1075 if (!asoc) {
1074 err = -ENOMEM; 1076 err = -ENOMEM;
@@ -1077,7 +1079,7 @@ static int __sctp_connect(struct sock* sk,
1077 } 1079 }
1078 1080
1079 /* Prime the peer's transport structures. */ 1081 /* Prime the peer's transport structures. */
1080 transport = sctp_assoc_add_peer(asoc, sa_addr, GFP_KERNEL, 1082 transport = sctp_assoc_add_peer(asoc, &to, GFP_KERNEL,
1081 SCTP_UNKNOWN); 1083 SCTP_UNKNOWN);
1082 if (!transport) { 1084 if (!transport) {
1083 err = -ENOMEM; 1085 err = -ENOMEM;
@@ -1101,8 +1103,8 @@ static int __sctp_connect(struct sock* sk,
1101 1103
1102 /* Initialize sk's dport and daddr for getpeername() */ 1104 /* Initialize sk's dport and daddr for getpeername() */
1103 inet_sk(sk)->dport = htons(asoc->peer.port); 1105 inet_sk(sk)->dport = htons(asoc->peer.port);
1104 af = sctp_get_af_specific(to.sa.sa_family); 1106 af = sctp_get_af_specific(sa_addr->sa.sa_family);
1105 af->to_sk_daddr(&to, sk); 1107 af->to_sk_daddr(sa_addr, sk);
1106 sk->sk_err = 0; 1108 sk->sk_err = 0;
1107 1109
1108 /* in-kernel sockets don't generally have a file allocated to them 1110 /* in-kernel sockets don't generally have a file allocated to them